# Account Status (/docs/account-status) Every account has a `status` that tells you whether it can publish. Check it before you publish, and reconnect an account as soon as it stops being `active`. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.getAccount({ id: "acc_YOUR_LINKEDIN_ACCOUNT_ID", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.get_account( "acc_YOUR_LINKEDIN_ACCOUNT_ID", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_LINKEDIN_ACCOUNT_ID" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "id": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "platform": "linkedin", "displayName": "Your Brand", "handle": "Your Brand", "avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "status": "active", "canAutoRenew": false, "tokenExpiresAt": "2027-04-30T10:00:00.000Z", "profile": "Default", "metadata": {}, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z" } ``` ## Status Values [#status-values] | `status` | Meaning | What to do | | --- | --- | --- | | `active` | The account works | Nothing | | `expired` | The access ran out and could not renew | [Reconnect the account](#reconnect-an-account) | | `revoked` | The platform or the owner withdrew the access | Reconnect the account | | `error` | The account cannot be used until reconnected | Reconnect the account | New values can be added, so treat anything but `active` as needing a reconnect. Until then, actions fail. The API does not return disconnected accounts. You see `disconnected` only in the [`account.disconnected`](/docs/webhooks/accounts#accountdisconnected) webhook. ## Token Expiry [#token-expiry] Two fields tell you whether an account stays connected on its own. | Field | Meaning | | --- | --- | | `canAutoRenew` | `true` when the access renews by itself, so expiry never needs a reconnect | | `tokenExpiresAt` | When the access expires, or `null` when it never does | When `canAutoRenew` is `false`, the account works until `tokenExpiresAt` and then reads `expired`. It depends on what the platform granted at sign-in, so check it per account. Each platform page lists its access lifetimes under **Connect**. ## Expiring Accounts [#expiring-accounts] An account that cannot renew sends [`account.expiring`](/docs/webhooks/accounts#accountexpiring) about 7 days before `tokenExpiresAt`, or right after connecting when less time is left. Reconnect it before then to keep publishing. | Event | When you get it | | --- | --- | | `account.expiring` | About 7 days before the access runs out. Once per authorization | | `account.expired` | The access ran out, the next time the account is used | | `account.revoked` | The platform rejected the access, or the owner withdrew it | | `account.connected` | A connect or reconnect, with `reconnected` and the new `tokenExpiresAt` | | `account.disconnected` | An account was disconnected | See [Account Webhooks](/docs/webhooks/accounts) for the payloads. ## Reconnect an Account [#reconnect-an-account] Reconnect when `status` is not `active`, when `account.expiring` arrives, or when a post fails with `TOKEN_INVALID`. The account keeps its id, profile and posts, and is not billed as new. `POST /v1/accounts/{id}/reconnect` needs a `read_write` key. Check `type` in the response. | `type` | Platforms | Response | | --- | --- | --- | | `oauth` | All except Bluesky | A sign-in `url` and its `expiresAt` | | `account` | Bluesky | The reconnected `account` | ### Platforms With a Sign-In [#platforms-with-a-sign-in] Send the `redirectUrl` the browser returns to. It is required with an API key. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.reconnectAccount({ id: "acc_YOUR_LINKEDIN_ACCOUNT_ID", reconnectAccountBody: { "redirectUrl": "https://yourapp.com/oauth/onepostly" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.reconnect_account( "acc_YOUR_LINKEDIN_ACCOUNT_ID", reconnect_account_body={ "redirectUrl": "https://yourapp.com/oauth/onepostly" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts/acc_YOUR_LINKEDIN_ACCOUNT_ID/reconnect" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "redirectUrl": "https://yourapp.com/oauth/onepostly" }' ``` **Response** ```json { "type": "oauth", "url": "https://www.linkedin.com/oauth/v2/authorization?response_type=code&state=eyJhbGciOiJIUzI1NiJ9", "expiresAt": "2027-03-15T10:10:00.000Z" } ``` Send the user to the `url` within 10 minutes. They must sign in with the same account, and no Page picker is shown. A success redirects with the usual parameters plus `reconnected=1`. Another account returns `error=RECONNECT_MISMATCH`. Other failures use the [Redirect Errors](/docs/connection#redirect-errors) codes. ### Bluesky [#bluesky] Send the `identifier` and a new `appPassword`. The identifier has to belong to the same Bluesky account. The response has `type` set to `account`, with the reconnected account in `account`. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.reconnectAccount({ id: "acc_YOUR_BLUESKY_ACCOUNT_ID", reconnectAccountBody: { "identifier": "yourbrand.bsky.social", "appPassword": "qrst-uvwx-yzab-cdef" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.reconnect_account( "acc_YOUR_BLUESKY_ACCOUNT_ID", reconnect_account_body={ "identifier": "yourbrand.bsky.social", "appPassword": "qrst-uvwx-yzab-cdef" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts/acc_YOUR_BLUESKY_ACCOUNT_ID/reconnect" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "identifier": "yourbrand.bsky.social", "appPassword": "qrst-uvwx-yzab-cdef" }' ``` **Response** ```json { "type": "account", "account": { "id": "acc_YOUR_BLUESKY_ACCOUNT_ID", "platform": "bluesky", "displayName": "Your Brand", "handle": "yourbrand.bsky.social", "avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "status": "active", "canAutoRenew": true, "tokenExpiresAt": "2027-03-15T12:00:00.000Z", "profile": "Default", "metadata": {}, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } } ``` ## Disconnect an Account [#disconnect-an-account] `DELETE /v1/accounts/{id}` needs a `read_write` key and returns `204`. Only YouTube also withdraws the access on the platform. Elsewhere, the owner can remove Onepostly in the platform's app settings. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.deleteAccount({ id: "acc_YOUR_LINKEDIN_ACCOUNT_ID", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.delete_account( "acc_YOUR_LINKEDIN_ACCOUNT_ID", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X DELETE "https://api.onepostly.com/v1/accounts/acc_YOUR_LINKEDIN_ACCOUNT_ID" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` | After a disconnect | Result | | --- | --- | | Published posts | Stay on the platform | | Its posts in Onepostly | Keep their history | | `GET /v1/accounts/{id}` | `404 ACCOUNT_NOT_FOUND` | | [Billing](/docs/pricing#account-pricing) | Stops counting from the next UTC day | | Webhook | [`account.disconnected`](/docs/webhooks/accounts#accountdisconnected) | An account is also disconnected when its owner removes Onepostly in Facebook, Instagram or Threads settings, or asks the platform to delete their data. Connecting it again counts as a new account. ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `REDIRECT_URL_REQUIRED` | 400 | No `redirectUrl` with an API key | Send `redirectUrl` | | `INVALID_REDIRECT_URL` | 400 | Not a full `https` URL, or has credentials | Send a full `https` URL | | `BLUESKY_RECONNECT_APP_PASSWORD` | 400 | `identifier` or `appPassword` is missing | Send both | | `RECONNECT_MISMATCH` | 400 | Another Bluesky account's identifier | Use the original account | | `FORBIDDEN` | 403 | A `read_only` key | Use a `read_write` key | | `ACCOUNT_NOT_FOUND` | 404 | No such account, or already disconnected | Use a current id | | `AUTH_FAILED` | 422 | Bluesky rejected the credentials | Create a new App Password | | `PLATFORM_MAINTENANCE` | 503 | Connections to the platform are paused | Try again later | See [Errors](/docs/error-handling#accounts-and-connections) for every other code. # Connect Accounts (/docs/connection) Connect a social account to your workspace before you publish to it. Connect your own accounts in the dashboard, or let your users connect theirs from your app. | Method | Platforms | Where the user signs in | | --- | --- | --- | | Dashboard | All | The **Connections** page in Onepostly | | Connect session | All except Bluesky | The platform's sign-in, then back to your app | | App Password | Bluesky | Nowhere. You send the handle and an App Password | Your first 2 accounts are free. A 3rd account needs a payment method first. See [Pricing and Wallet](/docs/pricing). ## Connect From the Dashboard [#connect-from-the-dashboard] Open **Connections** in the dashboard and pick a platform. Only owners and admins of the workspace can connect accounts. Sign in and approve access. On Facebook, pick a Page. On Instagram, choose **Instagram Login**, or **Facebook Login** and pick an account linked to one of your Pages. Copy the account id from the list, or get it with [List Accounts](#list-accounts). Each Facebook Page and each Instagram account is its own account. Repeat the steps to add another. ## Connect From Your App [#connect-from-your-app] Let your users connect their accounts without leaving your app. This works for every platform except Bluesky and needs a `read_write` API key. ### Create a Connect Session [#create-a-connect-session] **TypeScript** ```typescript import { Configuration, ConnectApi } from "@onepostly/sdk"; const connectApi = new ConnectApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await connectApi.createConnectSession({ createConnectSessionBody: { "platform": "x", "redirectUrl": "https://yourapp.com/oauth/onepostly", "profile": "Business", "metadata": { "userId": "user_8412" } }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.connect_api import ConnectApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: connect_api = ConnectApi(api_client) response = await connect_api.create_connect_session( create_connect_session_body={ "platform": "x", "redirectUrl": "https://yourapp.com/oauth/onepostly", "profile": "Business", "metadata": { "userId": "user_8412" } }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/connect-sessions" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "platform": "x", "redirectUrl": "https://yourapp.com/oauth/onepostly", "profile": "Business", "metadata": { "userId": "user_8412" } }' ``` **Response** ```json { "url": "https://x.com/i/oauth2/authorize?response_type=code&state=eyJhbGciOiJIUzI1NiJ9", "expiresAt": "2027-03-15T09:10:00.000Z" } ``` | Field | Description | | --- | --- | | `platform` | Required. Any platform id except `bluesky` | | `redirectUrl` | Required with an API key. The `https` URL the browser returns to. `http` works only on `localhost` | | `profile` | The [profile](/docs/profiles) for the account, created if missing. Defaults to `Default` | | `metadata` | Your own key-value pairs for the account, such as your user's id. Up to 20 keys of 1 to 40 characters, with string values up to 500 characters. See [Link Accounts to Your Users](#link-accounts-to-your-users) | | `loginMethod` | Instagram only. `instagram_login` (default) or `facebook_login` | | `headless` | `true` to build the [Page or account picker](#pick-a-page-or-account) yourself | The response has a `url` that expires after 10 minutes, at `expiresAt`. A later sign-in returns `SESSION_EXPIRED`, so create a new session for every attempt. Past the 2 free accounts without a payment method, this call returns `402 USAGE_BILLING_REQUIRED`. ### Send the User to the URL [#send-the-user-to-the-url] Open the `url` in the browser, as a full page or a popup. The user signs in on the platform and approves access. ### Handle the Redirect [#handle-the-redirect] When the user is done, the browser returns to your `redirectUrl` with these query parameters. | Parameter | Description | | --- | --- | | `connected` | The platform, such as `x` or `instagram` | | `accountId` | The account id. Use it as `accountId` when you publish | | `handle` | The account handle without a leading `@`, when the platform has one | | `count` | How many accounts were connected | | `reconnected` | `1` when the session came from [Reconnect Account](/docs/account-status#reconnect-an-account) | | `skipped` | How many accounts were not connected because the workspace needs a payment method | ``` https://yourapp.com/oauth/onepostly?connected=x&count=1&accountId=acc_1699f4157fb643f49d2ac447491f32a8&handle=yourbrand ``` Your own query parameters, such as `state`, come back unchanged. A `#fragment` is dropped. If the connect fails, the redirect has `error` and `error_description` instead. See [Redirect Errors](#redirect-errors). ### Link Accounts to Your Users [#link-accounts-to-your-users] Onepostly does not know who your users are. Send your user's id in `metadata` when you create the session, as the sample above does. The new account keeps it, and every account response and the [`account.connected`](/docs/webhooks/accounts#accountconnected) webhook return it. 1. Create the session with `metadata`, such as `{ "userId": "user_8412" }`. 2. When the redirect or `account.connected` arrives, read `metadata` from the account and save its `id` with that user. The webhook arrives even when the user closes the browser before the redirect, so handle both and keep the first. The redirect passes through the user's browser, where anyone can edit it. Read the account on your server with `GET /v1/accounts/{id}` and check its `metadata` before you trust an `accountId` from the redirect. An account gets its `metadata` once, when it is added. Connecting an account that is already in the workspace keeps the `metadata` it has. So when two of your users connect the same social account, both get the same `accountId` with the first user's `metadata`. Decide whether your app allows that, and change the keys later with [Update Metadata](#update-metadata). Your API key can publish to every account in the workspace. Before you publish for a user, check that the account is one you saved for them. Disconnecting an account erases its `metadata`, but the [`account.disconnected`](/docs/webhooks/accounts#accountdisconnected) event still carries it, so you can remove the link on your side. Keep secrets out of `metadata`. ### Update Metadata [#update-metadata] Change an account's `metadata` at any time with `PATCH /v1/accounts/{id}`. It needs a `read_write` key. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.updateAccount({ id: "acc_1699f4157fb643f49d2ac447491f32a8", updateAccountBody: { "metadata": { "team": "marketing" } }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.update_account( "acc_1699f4157fb643f49d2ac447491f32a8", update_account_body={ "metadata": { "team": "marketing" } }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X PATCH "https://api.onepostly.com/v1/accounts/acc_1699f4157fb643f49d2ac447491f32a8" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "metadata": { "team": "marketing" } }' ``` **Response** ```json { "id": "acc_1699f4157fb643f49d2ac447491f32a8", "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": "Business", "metadata": { "userId": "user_8412", "team": "marketing" }, "xSubscriptionType": "None", "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } ``` | You send | Result | | --- | --- | | `"key": "value"` | Sets the key | | `"key": null` | Removes the key | | A key you leave out | Keeps its value | | `"metadata": null` | Removes every key | The response is the updated account. An update that would leave more than 20 keys returns `400 VALIDATION_ERROR` and changes nothing. Remove keys with `null` in the same request to make room. ### Redirect Errors [#redirect-errors] A failed connect returns to your `redirectUrl` with two parameters. | Parameter | Description | | --- | --- | | `error` | A stable code from the table below. Build your logic on it | | `error_description` | A message you can show the user. The wording can change | ``` https://yourapp.com/oauth/onepostly?error=ACCESS_DENIED&error_description=The+sign-in+was+declined+or+cancelled. ``` | Code | Cause | What to do | | --- | --- | --- | | `ACCESS_DENIED` | The user declined or cancelled | Let the user start again | | `PLATFORM_ERROR` | The platform returned an error | Show `error_description`, then retry | | `SESSION_EXPIRED` | The sign-in finished after `expiresAt` | Create a new session | | `INVALID_CALLBACK` | No sign-in code, or a changed session | Create a new session | | `SESSION_MISMATCH` | The Onepostly user or workspace changed | Sign in to the right workspace and retry | | `FORBIDDEN` | The Onepostly user is not an owner or admin | Ask an owner or admin | | `PLATFORM_UNAVAILABLE` | The platform cannot be connected right now | Try again later | | `RECONNECT_MISMATCH` | A reconnect signed in with another account | Sign in with the original account | | `NO_ACCOUNTS` | No Page or linked account to connect | Set one up on the platform, then retry | | `USAGE_BILLING_REQUIRED` | No payment method past the 2 free accounts | Add a payment method in your dashboard | | `USAGE_BILLING_FAILED` | Billing for the account could not be set up | Check your payment method in the dashboard | | `AUTHORIZATION_FAILED` | The platform did not finish the sign-in | Try again. If it persists, contact support | | `CONNECT_FAILED` | The account could not be connected | Try again. If it persists, contact support | New codes can be added. Treat a code you do not know like `CONNECT_FAILED`. ### Pick a Page or Account [#pick-a-page-or-account] On Facebook, and on Instagram with Facebook Login, the user picks a Page or a Page-linked account after approving access. Onepostly shows this picker by default. To build the picker in your own app, create the session with `headless: true`. Right after the user approves access, the browser returns to your `redirectUrl` with these parameters instead of the usual ones. | Parameter | Description | | --- | --- | | `platform` | `facebook` or `instagram` | | `step` | `select_page` for Facebook, `select_instagram_account` for Instagram | | `connectSession` | The session id for the next two calls. It is valid for 10 minutes | List the user's Pages, or the Instagram accounts linked to them. **TypeScript** ```typescript import { Configuration, ConnectApi } from "@onepostly/sdk"; const connectApi = new ConnectApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await connectApi.listConnectCandidates({ sessionId: "CONNECT_SESSION", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.connect_api import ConnectApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: connect_api = ConnectApi(api_client) response = await connect_api.list_connect_candidates( "CONNECT_SESSION", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/connect-sessions/CONNECT_SESSION/candidates" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "123456789012345", "platform": "facebook", "name": "Your Brand", "username": "yourbrand", "pictureUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "category": "Brand", "pageName": null }, { "id": "123456789012346", "platform": "facebook", "name": "Your Brand Support", "username": "yourbrandsupport", "pictureUrl": "https://cdn.onepostly.com/avatars/yourbrandsupport.jpg", "category": "Product/service", "pageName": null } ] } ``` Each candidate has an `id`, `name`, `username` and `pictureUrl`. Pages also have a `category`. Instagram accounts have a `pageName`, the Page they are linked to. Send the candidate the user picked. **TypeScript** ```typescript import { Configuration, ConnectApi } from "@onepostly/sdk"; const connectApi = new ConnectApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await connectApi.selectConnectCandidate({ sessionId: "CONNECT_SESSION", selectConnectCandidateBody: { "candidateId": "123456789012345" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.connect_api import ConnectApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: connect_api = ConnectApi(api_client) response = await connect_api.select_connect_candidate( "CONNECT_SESSION", select_connect_candidate_body={ "candidateId": "123456789012345" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/connect-sessions/CONNECT_SESSION/select" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "candidateId": "123456789012345" }' ``` **Response** ```json { "account": { "id": "acc_1699f4157fb643f49d2ac447491f3204", "platform": "facebook", "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": "Business", "metadata": { "userId": "user_8412" }, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" }, "redirectUrl": "https://yourapp.com/oauth/onepostly?connected=facebook&count=1&accountId=acc_1699f4157fb643f49d2ac447491f3204&handle=yourbrand" } ``` The response has the new `account` and a `redirectUrl`. To finish on a different page than the session's `redirectUrl`, send `redirectUrl` in the body. Send the browser to the returned `redirectUrl`. It carries the same parameters as a normal redirect. ## Connect Bluesky [#connect-bluesky] Bluesky uses an App Password instead of a sign-in screen. In Bluesky, open **Settings → Privacy and Security → App Passwords** and create one. You can revoke it there at any time. Send the handle and the App Password. The account's email or DID also works in place of the handle. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.createAccount({ createAccountBody: { "platform": "bluesky", "identifier": "yourbrand.bsky.social", "appPassword": "abcd-efgh-ijkl-mnop", "profile": "Business", "metadata": { "userId": "user_8412" } }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.create_account( create_account_body={ "platform": "bluesky", "identifier": "yourbrand.bsky.social", "appPassword": "abcd-efgh-ijkl-mnop", "profile": "Business", "metadata": { "userId": "user_8412" } }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "platform": "bluesky", "identifier": "yourbrand.bsky.social", "appPassword": "abcd-efgh-ijkl-mnop", "profile": "Business", "metadata": { "userId": "user_8412" } }' ``` **Response** ```json { "id": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "bluesky", "displayName": "Your Brand", "handle": "yourbrand.bsky.social", "avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "status": "active", "canAutoRenew": true, "tokenExpiresAt": "2027-03-01T12:00:00.000Z", "profile": "Business", "metadata": { "userId": "user_8412" }, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z" } ``` The response is the new account, with `201`. Wrong credentials return `422 AUTH_FAILED`. `profile` and `metadata` work as in a connect session. To set default post languages for the account, see [Post Languages](/docs/bluesky#post-languages). ## Connect the Same Account Again [#connect-the-same-account-again] Connecting an account that is already in the workspace does not add a second one. | The account is | What happens | | --- | --- | | Connected | Its access is renewed. It keeps its `id`, profile and `metadata`, and it does not count as a new account. `account.connected` has `reconnected: true` | | Disconnected | It comes back as a new connection, with the profile and `metadata` the new connect names. It counts as a new account. `account.connected` has `reconnected: false` | To renew one account on purpose, use [Reconnect an Account](/docs/account-status#reconnect-an-account). It checks that the user signs in with the same account. ## List Accounts [#list-accounts] **TypeScript** ```typescript 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); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.list_accounts() print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "acc_1699f4157fb643f49d2ac447491f3203", "platform": "bluesky", "displayName": "Your Brand", "handle": "yourbrand.bsky.social", "avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "status": "active", "canAutoRenew": true, "tokenExpiresAt": "2027-03-01T12:10:00.000Z", "profile": "Business", "metadata": { "userId": "user_8412" }, "createdAt": "2027-03-01T10:10:00.000Z", "updatedAt": "2027-03-01T10:10:00.000Z" }, { "id": "acc_1699f4157fb643f49d2ac447491f3202", "platform": "instagram", "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": {}, "createdAt": "2027-03-01T10:05:00.000Z", "updatedAt": "2027-03-01T10:05:00.000Z" }, { "id": "acc_1699f4157fb643f49d2ac447491f32a8", "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": "Business", "metadata": {}, "xSubscriptionType": "None", "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z" } ], "nextCursor": null, "hasMore": false } ``` All parameters are optional, and you can combine them. | Parameter | Description | | --- | --- | | `limit` | Accounts per page, 1 to 100. Default `50` | | `cursor` | The `nextCursor` of the previous page | | `q` | Search by name, handle or platform, in any letter case | | `platform` | Only accounts on this platform, such as `instagram` | | `profile` | Only accounts in the profile with this name, in any letter case. `none` lists accounts without a profile | | `since`, `until` | Only accounts connected in this window. See [Time Filters](/docs/pagination#time-filters) | | `sort` | `created_desc` (default) for newest first, or `created_asc` for oldest first | | `include` | `total` adds the number of matching accounts | Pass `nextCursor` as `cursor` until `hasMore` is `false`. `GET /v1/accounts/{id}` reads one account. Disconnected accounts are never listed and return `404 ACCOUNT_NOT_FOUND`. ### Account Fields [#account-fields] | Field | Type | Description | | ------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | The account id, such as `acc_1699f4157fb643f49d2ac447491f32a8`. Use it as `accountId` when you publish. | | `platform` | `string` | The platform, such as `x`, `instagram` or `bluesky`. | | `displayName` | `string` | The account name on the platform. | | `handle` | `string` | The account handle on the platform, without a leading `@`, such as `yourbrand`. LinkedIn has no handles, so a LinkedIn account has its name here. | | `avatarUrl` | `string \| null` | The profile image URL. | | `status` | `"active" \| "expired" \| "revoked" \| "error"` | Check this before you publish. `active` means the account works. Any other value means the account cannot publish until you reconnect it. New values can be added. See [Account Status](/docs/account-status#status-values). | | `canAutoRenew` | `boolean` | `true` when access renews by itself. `false` means the user has to reconnect before `tokenExpiresAt`. | | `tokenExpiresAt` | `string \| null` | When the current access expires, or `null` when it does not expire. | | `profile` | `string \| null` | The name of the profile the account belongs to, such as `Business`. `null` when it has none. | | `metadata` | `Record` | Your own key-value pairs from the connect that added the account, such as `{ "userId": "user_8412" }`. An empty object when you sent none. See [Link Accounts to Your Users](#link-accounts-to-your-users). | | `xSubscriptionType` | `string \| null` | X only, and left out for other platforms. The account's X subscription, such as `Premium`. Any value other than `None` lets the account post up to 25,000 weighted characters. `null` when X does not report it. | | `createdAt` | `string` | When the account was connected. | | `updatedAt` | `string` | When the account last changed. | ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `VALIDATION_ERROR` | 400 | A field is missing or malformed, such as an empty Bluesky handle or a `platform` that has no connect session | Correct the field named in `param` | | `REDIRECT_URL_REQUIRED` | 400 | No `redirectUrl` was sent with an API key, or with `headless: true` | Add `redirectUrl` | | `INVALID_REDIRECT_URL` | 400 | `redirectUrl` is not a full URL, contains credentials, or uses `http` on a public host | Send a full `https` URL | | `INVALID_CONNECT_SESSION` | 400 | The `connectSession` is malformed, was changed, or is older than 10 minutes | Pass it unchanged, or create a new connect session | | `FACEBOOK_PAGES_FAILED` | 400 | Facebook did not return the user's Pages | Try again, or create a new connect session | | `INSTAGRAM_ACCOUNTS_FAILED` | 400 | Facebook did not return the linked Instagram accounts | Try again, or create a new connect session | | `CONNECT_FAILED` | 400 | The account could not be saved, or Bluesky could not sign in | Try again. If it keeps happening, contact support | | `USAGE_BILLING_REQUIRED` | 402 | The 2 free accounts are used and there is no payment method | Add a payment method in the dashboard, then connect again | | `USAGE_BILLING_FAILED` | 402 | Billing for the new account could not be set up, so it was not added | Check the payment method in the dashboard, then connect again | | `FORBIDDEN` | 403 | A `read_only` key, or a connect session from another workspace | Use a `read_write` key from the workspace that started the session | | `ACCOUNT_NOT_FOUND` | 404 | The account does not exist or was disconnected, or the `candidateId` is not one of the user's Instagram accounts | List the accounts or candidates again and use an id from the list | | `PAGE_NOT_FOUND` | 404 | The `candidateId` is not one of the user's Pages | List the candidates again and use an id from the list | | `AUTH_FAILED` | 422 | Bluesky rejected the handle or App Password | Check the handle and create a new App Password | | `PLATFORM_UNAVAILABLE` | 502 | The platform failed or did not respond, or accounts on it cannot be connected right now | Try again later. If it keeps happening, contact support | | `PLATFORM_MAINTENANCE` | 503 | New connections to this platform are paused for now | Try again later | Errors in the browser part of the flow come back on your redirect, not as an API response. See [Redirect Errors](#redirect-errors). Reconnect errors are on [Account Status](/docs/account-status#errors), and every code is in the [error catalog](/docs/error-handling#accounts-and-connections). # Profiles (/docs/profiles) A profile is a named group of accounts in your workspace. You name a profile when you connect an account, and you filter accounts and posts by that name. **TypeScript** ```typescript import { Configuration, ProfilesApi } from "@onepostly/sdk"; const profilesApi = new ProfilesApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await profilesApi.listProfiles(); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.profiles_api import ProfilesApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: profiles_api = ProfilesApi(api_client) response = await profiles_api.list_profiles() print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/profiles" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "name": "Default", "accountCount": 2, "createdAt": "2027-03-01T09:00:00.000Z", "updatedAt": "2027-03-01T09:00:00.000Z" }, { "name": "Business", "accountCount": 3, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z" } ], "nextCursor": null, "hasMore": false } ``` ## How Profiles Work [#how-profiles-work] | Rule | Detail | | --- | --- | | Identity | A profile has no id. Its `name` identifies it | | Names | 1 to 60 characters, unique in any letter case | | Reserved | `none`, the filter value for accounts without a profile | | Membership | One profile per account, or none. The account's `profile` is the name or `null` | | `accountCount` | Connected accounts only | The list is oldest first, 50 per page and up to 100 with `limit`. Pass `nextCursor` as `cursor` until `hasMore` is `false`. Any key can list profiles. Changes need a `read_write` key. A key [limited to some profiles](/docs/authentication#profile-access) lists only its own profiles and cannot change profiles. ## The Default Profile [#the-default-profile] Every workspace starts with a profile named `Default`. | You connect an account | It goes to | | --- | --- | | With a `profile` name | That profile. It is created if it does not exist | | Without a `profile` | `Default`. It is created again if you deleted it | This is the same in the dashboard and with an API key. ## Create a Profile [#create-a-profile] You rarely need this call, because a connect with a new `profile` name creates the profile for you. Create one ahead of time when you want it to exist before its first account. **TypeScript** ```typescript import { Configuration, ProfilesApi } from "@onepostly/sdk"; const profilesApi = new ProfilesApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await profilesApi.createProfile({ createProfileBody: { "name": "Business" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.profiles_api import ProfilesApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: profiles_api = ProfilesApi(api_client) response = await profiles_api.create_profile( create_profile_body={ "name": "Business" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/profiles" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Business" }' ``` **Response** ```json { "name": "Business", "accountCount": 0, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ``` The response is the new profile, with `201` and `accountCount` set to `0`. ## Add Accounts to a Profile [#add-accounts-to-a-profile] Send the profile name as `profile` when you connect the account. | Connect method | Where `profile` goes | | --- | --- | | Connect session | The body of [Create Connect Session](/docs/connection#create-a-connect-session) | | Bluesky | The body of [Connect Bluesky](/docs/connection#connect-bluesky) | An account keeps its profile when it is reconnected. There is no call that moves a connected account to another profile. To move one, disconnect it and connect it again with the new `profile`. A key limited to some profiles connects only into one of them. See [Profile Access](/docs/authentication#profile-access). ## Rename a Profile [#rename-a-profile] Send the current name URL-encoded in the path, such as `Client%20Team`, and the new name in the body. **TypeScript** ```typescript import { Configuration, ProfilesApi } from "@onepostly/sdk"; const profilesApi = new ProfilesApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await profilesApi.updateProfile({ name: "Business", updateProfileBody: { "name": "Acme Business" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.profiles_api import ProfilesApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: profiles_api = ProfilesApi(api_client) response = await profiles_api.update_profile( "Business", update_profile_body={ "name": "Acme Business" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X PATCH "https://api.onepostly.com/v1/profiles/Business" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Business" }' ``` **Response** ```json { "name": "Acme Business", "accountCount": 3, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } ``` The accounts stay, and filters use the new name from then on. A rename can also change only the letter case. ## Delete a Profile [#delete-a-profile] **TypeScript** ```typescript import { Configuration, ProfilesApi } from "@onepostly/sdk"; const profilesApi = new ProfilesApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await profilesApi.deleteProfile({ name: "Business", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.profiles_api import ProfilesApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: profiles_api = ProfilesApi(api_client) response = await profiles_api.delete_profile( "Business", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X DELETE "https://api.onepostly.com/v1/profiles/Business" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` It returns `204`. The accounts stay connected with `profile` set to `null`, and their posts do not change. While an API key is limited to the profile, the delete returns `409 PROFILE_IN_USE`. Delete those keys first. ## Filter by Profile [#filter-by-profile] | Request | Returns | | --- | --- | | `GET /v1/accounts?profile=Business` | The profile's connected accounts | | `GET /v1/posts?profile=Business` | The profile's posts, disconnected accounts included | | `GET /v1/accounts?profile=none` | Accounts with no profile | | `GET /v1/posts?profile=none` | Posts of accounts with no profile | The filter ignores letter case. A name that matches no profile returns an empty list, not an error. ## Your App's Users [#your-apps-users] Profiles are meant for a few groups, not one per user of your app. To know which of your users owns an account, keep that link in your own database. See [Link Accounts to Your Users](/docs/connection#link-accounts-to-your-users). ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `VALIDATION_ERROR` | 400 | The name is empty or over 60 characters | Send 1 to 60 characters | | `FORBIDDEN` | 403 | A `read_only` key, or a key limited to some profiles, tried a change | Use a `read_write` key with access to all profiles | | `PROFILE_NOT_FOUND` | 404 | No profile has this name | Use a current name | | `PROFILE_NAME_TAKEN` | 409 | The name is taken in any letter case, or is `none` | Choose another name | | `PROFILE_IN_USE` | 409 | An API key is limited to the profile | Delete those keys first | See [Errors](/docs/error-handling) for every other code. # Errors (/docs/error-handling) Every error has the same shape and a stable `code`. The code and the HTTP status tell you to fix the request, wait, or reconnect an account. ## Error Envelope [#error-envelope] Every error response has this body. ```json { "error": "Invalid request: geoRestriction entries must be uppercase ISO 3166-1 alpha-2 codes (e.g. \"US\").", "code": "VALIDATION_ERROR", "param": "accounts.0.x.geoRestriction.0", "requestId": "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" } ``` | Field | Type | Description | | ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------- | | `error` (required) | `string` | A message for people. Its wording can change, so do not build logic on it. | | `code` (required) | `string` | A stable code, such as VALIDATION_ERROR. Build your logic on it. | | `param` | `string` | The field at fault, as a dotted path such as accounts.0.accountId. A header uses its name, such as Idempotency-Key. | | `details` | `object` | Extra context. A 429 has limit, currentCount and retryAfterSeconds. A billing 402 has billingState. | | `platform` | `string` | The platform that refused the request, such as x or tiktok. | | `requestId` | `string` | The id of this request, also in the Request-Id header. Share it with support. | Empty fields are left out. A `code` never changes its meaning. New codes can appear, so handle an unknown one by its HTTP status. ## Request Ids [#request-ids] Every response has a `Request-Id` header, such as `req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c`. Errors repeat it as `requestId`. Log it so support can find the request. ## HTTP Status Codes [#http-status-codes] | Status | Meaning | What to do | | --- | --- | --- | | `400` | The request is invalid, or the platform lacks the action | Fix the request | | `401` | The API key is missing, invalid or deleted | Send a valid key. See [Authentication](/docs/authentication) | | `402` | Billing is blocked, a payment method is needed, or the wallet is short | Fix it in the dashboard. See [Pricing](/docs/pricing) | | `403` | The key is `read_only`, or this caller cannot take the action | Use a `read_write` key | | `404` | Nothing has this id here, or the id is of another kind | Check the id and its [prefix](/docs/ids) | | `409` | A reconnect is needed, the state is wrong, or an `Idempotency-Key` conflicts | Read `code`, then reconnect or check the state | | `422` | The platform refused, such as for a missing permission | Fix the cause in `code` | | `429` | A rate limit, or the platform is limiting the account | Wait for `Retry-After`. See [Handle 429](/docs/rate-limits#handle-429-responses) | | `500` | An unexpected error | Try again. If it repeats, contact support | | `502` | The platform failed or did not respond, for now | Try again later | | `503` | The action is paused, such as uploads or new connections | Try again later | A `400` or `422` sent again unchanged returns the same error. ## Publish Failures [#publish-failures] `POST /v1/posts` checks the whole request first. If any account cannot take the post, nothing is created. After a `201`, each post publishes on its own. A post that fails ends as `failed`, with the reason in `error`. ```json { "id": "pst_8b7f2c641e3d4f9ab2c56d0e8a4f1b27", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "status": "failed", "platformPostId": null, "url": null, "error": { "code": "MEDIA_UNFETCHABLE", "message": "Could not download media URL (HTTP 403)." } } ``` - The posts of one request share a `groupId`, but each succeeds or fails alone. X can be `published` while Instagram is `failed`. - A failed post is final. Fix the cause and create a new post. - The [`post.failed`](/docs/webhooks/posts#postfailed) webhook carries the same post. - `PUBLISH_INTERRUPTED` means the post may be live. Check the platform before you post again. - `TOKEN_INVALID` from any request marks the account for a [reconnect](/docs/account-status#reconnect-an-account). More in [Failed Posts](/docs/post-lifecycle#failed-posts). ## Webhook Failures [#webhook-failures] An event can arrive more than once, so skip any `id` you have handled. A failed delivery never affects publishing. Send it again with [Retry Delivery](/docs/api-reference/webhooks/retry-webhook-delivery). See [Delivery and Retries](/docs/webhooks#delivery-and-retries) for the full delivery rules. ## Billing [#billing] Billing errors return `402`. A blocked workspace gets `PAYMENT_METHOD_REQUIRED` or `PAYMENT_PAST_DUE` on every request, reads included. `details.billingState` names the cause. An X action the wallet cannot cover returns `INSUFFICIENT_WALLET`. See [Billing Blocks](/docs/pricing#billing-blocks). ## Best Practices [#best-practices] - Build logic on `code` and the status. Log `error`, `param`, `details` and `requestId`. - Send an `Idempotency-Key` with every `POST`, and reuse it on a retry. See [Idempotent Requests](/docs/idempotency). - Check each post's `status`. One request can publish on X and fail on Instagram. - Reconnect any account that is not `active` before a publish fails. See [Account Status](/docs/account-status). - Retry `429`, `500`, `502` and `503` after a wait. Fix the request on any other `4xx`. - Reconnect on `TOKEN_INVALID`, `TOKEN_EXPIRED` or `CONNECTION_INACTIVE`. ## Error Codes [#error-codes] Every code, grouped by area. In the Status column, **Post** means the code also shows in a post's `error.code`. **Analytics** means it shows in an analytics reading's `error`. Neither is an HTTP error. A code with several statuses lists them all. {/* Generated by generate-docs-data from the API error code catalog. Do not edit by hand. */} ### Requests and Authentication [#requests-and-authentication] | Code | Status | Cause | Fix | | --- | --- | --- | --- | | `VALIDATION_ERROR` | 400, Post | A field is missing, unknown or invalid, such as a wrong id kind, a long text, an unsupported option or a bad schedule. As a post error, the platform refused a parameter | Fix the field in `param` or `error` | | `INVALID_CURSOR` | 400 | `cursor` is not a `nextCursor` of this list | Use the last `nextCursor`, or drop `cursor` | | `UNAUTHORIZED` | 401 | The API key is missing, invalid or deleted | Send a valid key. See [Create an API Key](/docs/authentication#create-an-api-key) | | `FORBIDDEN` | 403 | A `read_only` key tried to write, a [key limited to some profiles](/docs/authentication#profile-access) managed profiles or named another profile, or another workspace started the connect session | Use a `read_write` key, a key with access to all profiles, or this workspace's key | | `GROUP_DISABLED` | 403 | The key's [restricted access](/docs/authentication#restrict-access) turned off this part of the API. `details.group` names it | Use a key that has the group | | `NOT_FOUND` | 404, Post | Nothing with this id exists in the workspace, or its prefix is wrong. As a post error, the post or its account was removed first | Check the id | | `IDEMPOTENCY_KEY_REUSED` | 409 | The `Idempotency-Key` was used for another request | Use a new key | | `IDEMPOTENCY_KEY_IN_USE` | 409 | A request with this `Idempotency-Key` is still running | Wait for `Retry-After`, then retry | | `RATE_LIMITED` | 429, Post, Analytics | An API or publishing limit was hit, or the platform slowed the account | Wait for `Retry-After` or the time in the message. See [Rate Limits](/docs/rate-limits) | | `QUOTA_EXCEEDED` | 429, Post, Analytics | The platform is at capacity for this action | Try again after the time in the message | | `INTERNAL_SERVER_ERROR` | 500 | An unexpected error | Try again later. If it repeats, contact support with the `requestId` | | `SERVICE_UNAVAILABLE` | 503 | The service is paused for now, such as media uploads | Try again later. If it repeats, contact support with the `requestId` | ### Billing and Wallet [#billing-and-wallet] | Code | Status | Cause | Fix | | --- | --- | --- | --- | | `PAYMENT_METHOD_REQUIRED` | 402 | The workspace has 3 or more accounts and no payment method | Add a payment method in the dashboard | | `PAYMENT_PAST_DUE` | 402 | A payment failed | Update the payment method and pay the invoice | | `INSUFFICIENT_WALLET` | 402, Post | The wallet cannot pay for an X action. Nothing is created or changed. As a post error, a scheduled X post was not covered at publish time | Top up the wallet, then retry. Check the balance with `GET /v1/wallet` | | `USAGE_BILLING_REQUIRED` | 402 | A 3rd account needs a payment method | Add a payment method, then connect again | | `USAGE_BILLING_FAILED` | 402 | Billing for the new account failed, so it was not connected | Check the payment method and connect again | ### Accounts and Connections [#accounts-and-connections] | Code | Status | Cause | Fix | | --- | --- | --- | --- | | `ACCOUNT_NOT_FOUND` | 404, Analytics | No account has this id in the workspace, or a picked Instagram account has no linked Page | Use an id from [List Accounts](/docs/connection#list-accounts) | | `CONNECTION_INACTIVE` | 409, Post, Analytics | The account is disconnected or its access was revoked | Reconnect the account | | `CONNECTION_BROKEN` | 409 | The Instagram account on Facebook Login has no linked Page | Reconnect the account | | `TOKEN_INVALID` | 409, Post, Analytics | The platform revoked the account's access. The account turns `revoked` and `account.revoked` is sent | Reconnect the account | | `TOKEN_EXPIRED` | 409, Post, Analytics | The platform says the account's access expired | Try again. If it repeats, reconnect | | `PERMISSION_DENIED` | 422, Post | A permission is missing, or the platform refused the action | Reconnect and approve every permission. On TikTok, the message may ask for a private account | | `ACCOUNT_RESTRICTED` | 422, Post, Analytics | X or TikTok restricted the account, such as a suspension or posting ban | Fix it on the platform, then try again | | `ACCOUNT_SUSPENDED` | 422, Post, Analytics | Bluesky took down, suspended or deactivated the account | Restore the account on Bluesky | | `AUTH_FAILED` | 422 | Bluesky rejected the handle or App Password | Check the handle and create a new App Password | | `CONNECT_FAILED` | 400 | The account could not be connected, such as when it already is | Check for an existing account | | `RECONNECT_MISMATCH` | 400 | A reconnect used another account | Reconnect with the same account | | `BLUESKY_RECONNECT_APP_PASSWORD` | 400 | A Bluesky reconnect has no `identifier` and `appPassword` | Send both | | `INVALID_REDIRECT_URL` | 400 | `redirectUrl` is not HTTPS or has credentials. HTTP works only for localhost | Send a valid HTTPS URL | | `REDIRECT_URL_REQUIRED` | 400 | The connect session or reconnect needs a `redirectUrl` | Send `redirectUrl` | | `INVALID_CONNECT_SESSION` | 400 | `connectSession` is malformed, changed or over 10 minutes old | Create a new connect session | | `FACEBOOK_PAGES_FAILED` | 400 | The user's Facebook Pages could not be listed | Try again, or create a new connect session | | `INSTAGRAM_ACCOUNTS_FAILED` | 400 | The linked Instagram accounts could not be listed | Try again, or create a new connect session | | `PAGE_NOT_FOUND` | 404 | The user cannot access the picked Facebook Page | Pick a Page from the candidates | | `PLATFORM_MAINTENANCE` | 503 | New connections to this platform are paused | Try again later | | `PROFILE_IN_USE` | 409 | An API key is limited to the profile you tried to delete | Delete the keys limited to it first | | `PROFILE_NAME_TAKEN` | 409 | The name exists in any letter case, or is reserved | Choose another name | | `PROFILE_NOT_FOUND` | 404 | No profile has the name in the path | List the profiles and use a current name | | `UNSUPPORTED_PLATFORM` | 400, Analytics | The account's platform does not have this action | Use an account on a supported platform | | `STATS_FAILED` | 502 | The platform did not return account stats | Try again. Reconnect if the message says so | | `LIST_FAILED` | 502 | The platform did not return the account's media or posts | Try again. Reconnect if the message says so | | `REVIEWS_FAILED` | 502 | Facebook did not return the Page reviews | Try again. Reconnect if it keeps failing | | `PROFILE_FAILED` | 502 | Facebook did not read or update the Messenger profile | Check the input and try again | | `CREATOR_INFO_FAILED` | 502, Post | TikTok creator info did not load. Creating or editing a TikTok post needs it, so nothing is created | Try again. Reconnect if it keeps failing | | `BOARDS_FAILED` | 502 | Pinterest boards could not be listed | Try again. Reconnect if it keeps failing | | `BOARD_CREATE_FAILED` | 502 | Pinterest did not create the board | Check the message and try again | | `SANDBOX_MISMATCH` | Post | The Pinterest account cannot publish in the current Pinterest environment | Disconnect and reconnect Pinterest | ### Media [#media] | Code | Status | Cause | Fix | | --- | --- | --- | --- | | `UNSUPPORTED_MEDIA_TYPE` | 400, Post | The file type is not supported | Use a [supported format](/docs/media-uploads#supported-formats) | | `MEDIA_NOT_FOUND` | 404 | A `media[].id` does not exist in this workspace | Use an id from `GET /v1/media` | | `MEDIA_NOT_UPLOADED` | Post | The file was never uploaded, or the upload expired | Upload the file, then create the post again | | `MEDIA_TYPE_MISMATCH` | Post | The uploaded file's type is not its `contentType` | Create a new media item with the right type | | `MEDIA_TOO_LARGE` | 400, Post | The file is over the [size limit](/docs/media-uploads#supported-formats) for its type | Upload a smaller file | | `MEDIA_UNFETCHABLE` | Post | The media URL could not be downloaded | Meet the [Media URL Requirements](/docs/media-uploads#media-url-requirements) | | `INVALID_MEDIA` | Post | The platform refused the file's format, count, size or kind | Check the platform's media requirements | | `MEDIA_REQUIRED` | Post | A media post has no media | Add `media` | | `MEDIA_UPLOAD_FAILED` | Post | The platform refused or failed the upload | Check the media and post again | | `MEDIA_PROCESSING_FAILED` | Post | X could not process the media | Re-encode the file and post again | | `MEDIA_PROCESSING_TIMEOUT` | Post | The platform did not process the media in time | Use a smaller or shorter file and post again | | `CONTAINER_FAILED` | 502, Post | Instagram or Threads could not process the media | Check the format and size, then post again | | `URL_OWNERSHIP_UNVERIFIED` | Post | TikTok refuses media from the URL's domain | Upload the file and use its `id` | | `REEL_UPLOAD_FAILED` | Post | Facebook did not accept the reel upload | Create the post again | | `STORY_UPLOAD_FAILED` | Post | Facebook did not accept the story upload | Create the post again | ### Publishing [#publishing] | Code | Status | Cause | Fix | | --- | --- | --- | --- | | `PUBLISH_FAILED` | 502, Post | The platform refused the post without a specific reason | Read `error.message`, fix the content and post again | | `PUBLISH_INTERRUPTED` | Post | The outcome is unknown, and the post may be live | Check the platform before posting again | | `PLATFORM_UNAVAILABLE` | 502, Post, Analytics | The platform is down or did not respond. Connecting or reconnecting an account can return it too | Try again later. If it repeats, contact support with the `requestId` | | `POST_NOT_PUBLISHED` | 409 | `quotePostId` or `replyToPostId` names a `pst_` post that is not live | Wait until it is live, or use the platform's post id | | `TEXT_TOO_LONG` | 400, 422, Post | The text is over the platform or account limit | Shorten it. See [Text Limits](/docs/platforms#text-limits) | | `TEXT_REQUIRED` | 400, 422, Post | A text post or message has no text | Add text | | `CAPTION_TOO_LONG` | Post | The Instagram caption is over 2,200 characters | Shorten the caption | | `INVALID_FIRST_COMMENT` | Post | The Instagram `firstComment` is over 2,200 characters | Shorten the comment | | `INVALID_AI_LABEL` | Post | Instagram `isAiGenerated` was sent on a story | Remove it, or post a reel or feed post | | `UNSUPPORTED_MEDIA_KIND` | Post | The platform cannot publish this `mediaKind` | Use a `mediaKind` the platform supports | | `UNSUPPORTED_FEATURE` | Post | The platform has no threads, quotes or replies | Remove `thread`, `quotePostId` or `replyToPostId` | | `INVALID_MULTI_IMAGE` | Post | The image count is outside the platform's range | Send a count the platform accepts | | `DUPLICATE_CONTENT` | 422, Post | X rejected the text as a duplicate | Change the text | | `GEO_RESTRICTION_FAILED` | Post | X rejected the `geoRestriction` list | Check the country codes, or remove `geoRestriction` | | `INVALID_LINK` | Post | The Bluesky `link` is not a valid URL | Fix the link | | `INVALID_QUOTE` | Post | The Bluesky post to quote is not a valid `at://` URI or was not found | Use an existing post's `pst_` id or `at://` URI | | `INVALID_REPLY` | Post | The Bluesky post to reply to is not a valid `at://` URI or was not found | Use an existing post's `pst_` id or `at://` URI | | `INVALID_TOPIC_TAG` | Post | The Threads `topicTag` is over 50 characters or has `.` or `&` | Fix the tag | | `INVALID_AUDIO` | Post | Instagram `audioId` needs a single video with `mediaKind` `reel` or `video`, on Facebook Login | Use a single video, or reconnect with Facebook Login | | `INVALID_SPONSOR` | Post | An Instagram sponsor was not found, or a paid partnership was sent without Facebook Login | Use a valid username or id, or reconnect with Facebook Login | | `INVALID_TRIAL_REEL` | Post | An Instagram trial reel is not a single video, or has sponsors | Use a single video without sponsors | | `INVALID_CAROUSEL` | Post | Facebook `carouselCards` needs `multi_image` and one card per image | Send one card per image with `multi_image` | | `TEXT_FORMAT_UNSUPPORTED` | Post | Facebook `textFormatPresetId` only works on text-only posts | Remove it, or post text only | | `PRIVACY_LEVEL_REQUIRED` | Post | The TikTok `privacyLevel` is missing or invalid | Send a valid `privacyLevel` | | `INVALID_PRIVACY_LEVEL` | 400, Post | The creator does not allow this TikTok `privacyLevel`. As a post error, their settings changed after scheduling | Use a value from `GET /v1/accounts/{id}/creator-info` | | `INTERACTION_DISABLED` | 400 | `tiktok.allowComment`, `allowDuet` or `allowStitch` is `true`, but the creator turned it off. Nothing is created | Set the option named in `error` to `false`. See `GET /v1/accounts/{id}/creator-info` | | `SPAM_RISK` | Post | TikTok flagged the post as a spam risk | Review the content before posting again | | `POSTING_LIMIT_REACHED` | Post | TikTok says the account posted too often | Wait before posting to this account again | | `CAPACITY_LIMITED` | Post | TikTok is not accepting more direct posts right now | Try again in a few hours | | `UPLOAD_LIMIT_EXCEEDED` | Post | The YouTube channel reached its upload limit | Wait until YouTube's limit resets | ### Edit, Cancel and Delete [#edit-cancel-and-delete] | Code | Status | Cause | Fix | | --- | --- | --- | --- | | `NOT_EDITABLE` | 409 | The post is not `scheduled`, or was made outside Onepostly | Delete it and create a new post | | `POST_PUBLISHING` | 409 | The post is publishing right now | Try again once its `status` is final | | `NOT_DELETABLE` | 409 | Nothing is on the platform. The post failed first, or was made outside Onepostly | Delete it in the platform's app, if it is there | | `DELETE_FAILED` | 502 | The platform did not delete the post | Try again later, and check the platform | | `DELETE_PERMISSION` | 422 | The account cannot delete this post | Reconnect and approve every permission, or check the account owns it | | `THREAD_DELETE_PARTIAL` | 502 | The first post was deleted, but not all of its thread | Send the delete again | | `MEDIA_DELETE_UNSUPPORTED` | 400 | Instagram Login accounts cannot delete media | Reconnect with Facebook Login, or use the Instagram app | | `INVALID_EXTERNAL_ID` | 400, Analytics | The Bluesky post id is not an `at://` URI | Use the `at://` URI as `platformPostId` | ### Comments and Engagement [#comments-and-engagement] | Code | Status | Cause | Fix | | --- | --- | --- | --- | | `NOT_PUBLISHED` | 409, Analytics | The post is not published yet | Wait until it publishes, then call again | | `ACCOUNT_REQUIRED` | 400 | A platform post id was sent without `accountId` | Send `accountId` too | | `AMBIGUOUS_TARGET` | 400 | The post was published to several accounts | Send `accountId` to pick one | | `POST_ACCOUNT_MISMATCH` | 400 | A like, bookmark or repost names another account's `pst_` post | Act as the post's account, or use `platformPostId` | | `TARGET_SYNC_FAILED` | 502 | The `platformPostId` post did not load from the platform | Check the id and try again | | `MISSING_EXTERNAL_ID` | 404, Analytics | The post or comment has no usable platform id | Pass a valid id | | `NOT_A_COMMENT` | 400 | The id is one of your posts, not a comment | Use `DELETE /v1/posts/{id}` | | `COMMENT_CREATE_FAILED` | 502 | The platform did not post the comment or reply | Try again | | `COMMENT_DELETE_FAILED` | 502 | The platform did not delete the comment | Try again | | `COMMENT_HIDE_FAILED` | 502 | The platform did not hide or unhide the comment | Try again | | `COMMENT_LIKE_FAILED` | 502 | Facebook did not like the comment | Try again | | `COMMENT_UNLIKE_FAILED` | 502 | Facebook did not remove the like | Try again | | `PRIVATE_REPLY_FAILED` | 502 | The private reply was not sent. A comment takes one, within 7 days | Check the comment's age and past replies | | `COMMENTS_PERMISSION` | 422 | A comment permission is missing, the comment cannot be deleted, or comments are off | Reconnect and approve every permission. On YouTube, check comments are on | | `COMMENTS_UNSUPPORTED` | 400 | Comments cannot be read for this post | Nothing to do | | `UNSUPPORTED_MEDIA` | 400 | The post is a story, which has no comments | Nothing to do | | `COMMENTS_FAILED` | 502 | The comments could not be read | Try again | | `INVALID_PARENT` | 400 | The Bluesky comment to reply to has an invalid id | Use a `cmt_` id from List Comments | | `INVALID_COMMENT_ID` | 400 | The Bluesky comment id is invalid | Use a `cmt_` id from List Comments | | `RESOLVE_FAILED` | 404 | Bluesky could not find the post or comment to reply to | Check that it still exists | | `ENGAGEMENT_FAILED` | 502 | The like or bookmark failed | Try again. Reconnect if the message says so | | `ENGAGEMENT_PERMISSION` | 422 | The account is missing permission for likes or bookmarks | Reconnect and approve every permission | | `LIKE_FAILED` | 502 | The platform did not like the post | Try again | | `UNLIKE_FAILED` | 502 | The platform did not remove the like | Try again | | `BOOKMARK_FAILED` | 502 | The platform did not bookmark the post | Try again | | `UNBOOKMARK_FAILED` | 502 | The platform did not remove the bookmark | Try again | | `REPOST_FAILED` | 502 | The platform did not repost the post | Try again | | `UNREPOST_FAILED` | 502 | The platform did not remove the repost | Try again | | `REPOST_PERMISSION` | 422 | The account cannot repost | Reconnect and approve every permission | | `UNREPOST_PERMISSION` | 422 | The account cannot remove the repost | Reconnect and approve every permission | | `UNREPOST_REQUIRES_REPOST_ID` | 400 | The Threads repost was not made through Onepostly | Undo it in the Threads app | | `REPOSTS_UNSUPPORTED` | 400 | Reposts cannot be read for this post | Nothing to do | | `REPOSTS_UNAUTHORIZED` | 422 | X rejected the account's access while reading reposts | Reconnect the account | | `REPOSTS_FAILED` | 502 | The reposts could not be read | Try again | | `READ_FAILED` | 502 | The platform list could not be read | Try again | | `SYNC_FAILED` | 502 | `POST /v1/accounts/{id}/sync` could not load the account's posts | Try again | ### Inbox and Automations [#inbox-and-automations] | Code | Status | Cause | Fix | | --- | --- | --- | --- | | `CONVO_NOT_FOUND` | 404 | The conversation does not exist | Check the `cnv_` id | | `RECIPIENT_NOT_FOUND` | 404 | The recipient does not exist. Facebook needs the numeric user id | Check the recipient | | `RECIPIENT_UNREACHABLE` | 409 | The recipient does not accept messages from this account | Reach them another way | | `MESSAGE_WINDOW_EXPIRED` | 409 | The 24-hour Instagram or Facebook messaging window closed | Wait for the person to message again | | `CONVO_LOCKED` | 409 | The Bluesky conversation is locked | Nothing to do | | `INBOX_PERMISSION` | 422 | The account is missing messaging permission | Reconnect and approve every permission | | `INBOX_FAILED` | 502 | The platform did not complete the inbox request | Try again. Reconnect if it keeps failing | | `INVALID_ATTACHMENT` | 400 | `attachmentUrl` is not an HTTPS URL | Use a public HTTPS URL | | `ATTACHMENT_UNSUPPORTED` | 400 | Attachments only work on Instagram and Facebook | Remove the attachment | | `TEMPLATE_UNSUPPORTED` | 400 | Quick replies, buttons and cards only work on Instagram and Facebook | Remove them | | `INVALID_TEMPLATE` | 400 | A button lacks `url` or `payload`, or an attachment has buttons or cards | Fix the buttons | | `LIMIT_REACHED` | 400 | The account has the most automations it can have | Delete an automation first | | `CONFLICT` | 409 | The automations changed while the request ran | Send the request again | ### Analytics [#analytics] | Code | Status | Cause | Fix | | --- | --- | --- | --- | | `INVALID_RANGE` | 400 | `since` is not before `until`, or the range is too long | Fix the dates | | `TIMELINE_UNSUPPORTED` | 400 | X posts have no daily timeline | Use `GET /v1/posts/{id}/analytics` | | `ANALYTICS_PERMISSION` | 422, Analytics | The account is missing the insights permission | Reconnect and approve every permission | | `ANALYTICS_FAILED` | 502, Analytics | The platform did not return metrics | Try again later. Reconnect if the message says so | | `ANALYTICS_PENDING` | Analytics | The platform has no metrics yet | Read again later | | `POST_NOT_FOUND` | Analytics | The post was deleted, or the account cannot see it. The reading is `unavailable` for good | Check the post on the platform | | `VIDEO_ID_PENDING` | Analytics | The TikTok video is not public yet | Read again later | | `VIDEO_NOT_FOUND` | Analytics | TikTok has no metrics yet, or the YouTube video was removed | Read again later, or check the video exists | | `PRIVACY_RESTRICTED` | Analytics | TikTok only reports metrics for public posts | Publish with `public_to_everyone` | ### Webhooks [#webhooks] | Code | Status | Cause | Fix | | --- | --- | --- | --- | | `CREATE_FAILED` | 500 | The webhook endpoint could not be created | Try again. If it repeats, contact support with the `requestId` | | `DELIVERY_IN_PROGRESS` | 409 | The delivery is still being attempted | Wait for `success` or `failed`, then retry | See [Analytics Status](/docs/analytics#analytics-status) for how the analytics codes relate to `status`. # Idempotent Requests (/docs/idempotency) A request can time out after the API already acted on it. With an `Idempotency-Key`, a retry never creates a second post, upload or message. ## Send an Idempotency Key [#send-an-idempotency-key] Every `POST` takes an `Idempotency-Key` header. Use a new value of up to 255 characters per request, such as a UUID. On a timeout or a dropped connection, send the same request again with the same key. **TypeScript** ```typescript import { Configuration, PostsApi } from "@onepostly/sdk"; const postsApi = new PostsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await postsApi.createPost({ idempotencyKey: "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d", createPostBody: { "text": "Release notes are live.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( idempotency_key="5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d", create_post_body={ "text": "Release notes are live.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Idempotency-Key: 5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" \ -H "Content-Type: application/json" \ -d '{ "text": "Release notes are live.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "Release notes are live.", "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" } ] } ``` The SDKs call it `idempotencyKey` in TypeScript and `idempotency_key` in Python. Create the key once, such as with `randomUUID()` or `uuid.uuid4()`, and reuse it on every retry of the same request. A key over 255 characters returns `400 VALIDATION_ERROR`. Requests without the header run as usual. `GET`, `PATCH` and `DELETE` ignore it. ## Replays [#replays] A reused key is matched against the first request with that key. Keys belong to the workspace, so all its API keys share them. | Second request | Response | | --- | --- | | Same method, path and body, within 24 hours | The first response, with `Idempotent-Replayed: true` | | Another path or body | `409 IDEMPOTENCY_KEY_REUSED` | | While the first is still running | `409 IDEMPOTENCY_KEY_IN_USE` with `Retry-After` | | After 24 hours | Runs as a new request | A replay runs nothing again. ## What Is Kept [#what-is-kept] | First response | Kept | What to do | | --- | --- | --- | | `2xx` | Yes | Nothing. A retry gets the same response | | `4xx` other than `429` | Yes | Fix the request and use a new key | | `429` | No | Wait for `Retry-After`, then retry with the same key | | `5xx` | No | Retry with the same key | A kept response replays, errors included. Otherwise the retry runs again. ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `VALIDATION_ERROR` | 400 | The key is over 255 characters | Use a shorter key, such as a UUID | | `IDEMPOTENCY_KEY_REUSED` | 409 | The key was used for another path or body | Use a new key | | `IDEMPOTENCY_KEY_IN_USE` | 409 | A request with this key is still running | Wait for `Retry-After`, then retry | Other codes are in [Errors](/docs/error-handling#error-codes). # Data Formats (/docs/ids) These rules hold for every endpoint and every webhook. Build your client on them, and it keeps working as the API grows. ## Id Prefixes [#id-prefixes] Every id starts with a prefix that names its kind. | Prefix | Points to | Example | | --- | --- | --- | | `acc_` | Account | `acc_1699f4157fb643f49d2ac447491f32a8` | | `pst_` | Post | `pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73` | | `grp_` | Posts of one create request | `grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45` | | `med_` | Media | `med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b` | | `whk_` | Webhook endpoint | `whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58` | | `dlv_` | Webhook delivery | `dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49` | | `aut_` | Automation | `aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33` | | `cmt_` | Comment | Varies in length | | `cnv_` | Conversation | Varies in length | | `evt_` | Webhook event | `evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72` | | `req_` | API request | `req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c` | An id with the wrong prefix fails fast. | Where you send it | Response | | --- | --- | | In the path | `404 NOT_FOUND`, or `ACCOUNT_NOT_FOUND` on account paths | | In the body or query | `400 VALIDATION_ERROR` with the field in `param` | ### Opaque Ids [#opaque-ids] Treat ids as opaque strings. Do not parse them, build them or rely on their length. A 512-character string column fits every kind. `cmt_` and `cnv_` ids belong to your workspace. They stay the same there, so you can store them. Another workspace gets other ids, and yours return `404 NOT_FOUND` there. Get them from [List Comments](/docs/comments#list-comments) and the [Inbox](/docs/inbox). An `evt_` id names one webhook event. Every retry of that event carries the same id, so use it to skip handled events. See [Webhooks](/docs/webhooks). ### Platform Ids [#platform-ids] Fields named `platform...`, such as `platformPostId`, hold the platform's own id. The platform sets its format, such as a number on X or an `at://` URI on Bluesky. Some fields take both kinds. `quotePostId` takes a `pst_` id or a platform post id. See [Post References](/docs/replies-and-quotes#post-references). The `platform` field holds one of these. | `platform` | Platform | | --- | --- | | `x` | X (Twitter) | | `instagram` | Instagram | | `facebook` | Facebook | | `threads` | Threads | | `linkedin` | LinkedIn | | `youtube` | YouTube | | `tiktok` | TikTok | | `pinterest` | Pinterest | | `bluesky` | Bluesky | ## Timestamps [#timestamps] Response timestamps are ISO 8601 in UTC with milliseconds, such as `2027-03-15T13:00:00.000Z`. These fields differ. | Field | Format | Example | | --- | --- | --- | | `scheduledFor` | Local time in `timezone`, no zone. See [Scheduling](/docs/scheduling#schedule-a-post) | `2027-03-15T09:00:00` | | `timezone` | IANA time zone | `America/New_York` | | Timeline `day` | UTC date | `2026-08-01` | | `X-RateLimit-Reset` | Unix seconds | `1789473600` | | `Retry-After` | Seconds to wait | `12` | In requests, `since` and `until` need `Z` or an offset. See [Time Filters](/docs/pagination#time-filters). ## Open Enums [#open-enums] Response fields can gain new values. Handle a value you do not know. | Field | Known values | | --- | --- | | Post `status` | [Post Status](/docs/post-lifecycle#post-status) | | `platform` | [Platform Ids](#platform-ids) | | `mediaKind` | [Media Kinds](/docs/publishing#media-kinds) | | Error `code` | [Error Codes](/docs/error-handling#error-codes) | | Account `status` | [Account Status](/docs/account-status) | | Media `status` | [Media](/docs/media-uploads) | | Analytics `status` | [Analytics Status](/docs/analytics#analytics-status) | | Delivery `status` | [Delivery Log](/docs/webhooks#delivery-log) | - An unknown post `status` is not final. Read the post again later. - An unknown account `status` may need attention, like any status but `active`. - Handle an unknown error `code` by its [HTTP status](/docs/error-handling#http-status-codes). - The SDKs accept any string here, so they read values added later. Responses can gain fields, so ignore ones you do not know. Requests are strict, and an unknown field or value returns `400 VALIDATION_ERROR`. ## Null Fields [#null-fields] A field without a value is `null`, not left out. A few platform-only fields, such as `xSubscriptionType`, are left out on other platforms. | Field | `null` means | | --- | --- | | `platformPostId`, `url`, `publishedAt` | Not published yet | | `scheduledFor`, `timezone` | Not scheduled | | `error` | Did not fail | | `metrics` | No metrics yet | | One metric, such as `metrics.saves` | Not reported for this post | | `groupId`, `text` | Made outside Onepostly | | `nextCursor` | Last page | Lists are never `null`. No media is `media: []`, and no options is `options: {}`. These are left out instead of `null`. - [Error envelope](/docs/error-handling#error-envelope) fields that do not apply, such as `param`. - [Include](/docs/pagination#include) extras you did not ask for, such as `total`. # Pagination and Filters (/docs/pagination) Every list pages the same way, and every time-based list takes the same time filter. This page also covers `sort` and `include`. ## Pagination [#pagination] Every list returns `data`, `nextCursor` and `hasMore`. ```json { "data": [{ "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" }], "nextCursor": "eyJrZXkiOjE4MDM...", "hasMore": true } ``` | Field | Meaning | | --- | --- | | `data` | The items of this page | | `nextCursor` | The `cursor` of the next page, `null` on the last | | `hasMore` | `true` when another page follows | Pass `nextCursor` as `cursor` until `hasMore` is `false`. Send the cursor unchanged, and keep the other parameters the same. Leave `cursor` out to start over. On lists such as posts, accounts and media, a changed or foreign cursor returns `400 INVALID_CURSOR`. **TypeScript** ```ts import { Configuration, PostsApi } from "@onepostly/sdk"; const postsApi = new PostsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); let cursor: string | undefined; do { const page = await postsApi.listPosts({ status: "published", limit: 100, cursor }); for (const post of page.data) { console.log(post.id, post.url); } cursor = page.nextCursor ?? undefined; } while (cursor); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) cursor = None while True: page = await posts_api.list_posts(status="published", limit=100, cursor=cursor) for post in page.data: print(post.id, post.url) if not page.has_more: break cursor = page.next_cursor asyncio.run(main()) ``` ### Page Size [#page-size] `limit` sets the page size of a list. A value below 1 or above the maximum for that list returns `400 VALIDATION_ERROR`. | List | Default | Maximum | | --- | --- | --- | | Most lists | 50 | 100 | | Comments and Facebook Page reviews | 50 | 50 | | Account media | 20 | 20 | Comments, reviews and account media follow the platform's page size. Each endpoint in the [API Reference](/docs/api-reference) lists its limit. ## Time Filters [#time-filters] Time-based lists and reports take `since` and `until`. | Rule | Detail | | --- | --- | | Format | ISO 8601 with `Z` or an offset, such as `2026-08-01T00:00:00Z` | | `since` | Inclusive | | `until` | Exclusive | | Defaults | Each endpoint has its own, see below | | Order | `since` must be before `until` | A date alone or a time without a zone returns `400 VALIDATION_ERROR`. A `since` after `until` returns `400 INVALID_RANGE`. Since `until` is exclusive, one window ends where the next begins. For all of August, send `since=2026-08-01T00:00:00Z` and `until=2026-09-01T00:00:00Z`. Encode `+` as `%2B` in a query string. | Endpoint | Filters on | Default | | --- | --- | --- | | `GET /v1/posts` | Schedule, else publish, else creation time | No limit | | `GET /v1/accounts` | Connection time | No limit | | `GET /v1/webhooks/{id}/deliveries` | Delivery time | The last 7 days | | `GET /v1/posts/{id}/analytics/timeline` | UTC days | 90 days, also the maximum | | `GET /v1/accounts/{id}/analytics` | The insights period | The platform's default | Deliveries are kept for your plan's log retention. A `since` older than that starts at the oldest delivery that is still kept. ## Sorting [#sorting] Some lists take `sort`, a field and a direction, such as `created_desc` for newest first. Every other list has a fixed order, mostly newest first. | List | `sort` values | Default | | --- | --- | --- | | `GET /v1/posts` | `created_*`, `published_*`, `scheduled_*`, `metric:` | `created_desc` | | `GET /v1/accounts` | `created_desc`, `created_asc` | `created_desc` | Each `*` is `desc` or `asc`. See [List Posts](/docs/publishing#list-posts) for the metric sorts. ## Include [#include] Some lists add extras when you ask with `include`, a comma-separated list. | List | `include` | Adds | | --- | --- | --- | | `GET /v1/posts` | `total`, `facets` | Total, and counts per status and platform | | `GET /v1/accounts` | `total` | Total | | `GET /v1/media` | `total` | Total | | `GET /v1/webhooks/{id}/deliveries` | `facets`, `histogram` | Counts per status, and results over time | `total` counts every match across all pages. An unknown value returns `400 VALIDATION_ERROR` with the accepted values. ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `VALIDATION_ERROR` | 400 | A bad `limit`, time format, `sort` or `include` | Fix the field in `param` | | `INVALID_CURSOR` | 400 | `cursor` is not from this list | Use the last `nextCursor`, or drop `cursor` | | `INVALID_RANGE` | 400 | `since` is not before `until`, or the range is too long | Fix the dates | Other codes are in [Errors](/docs/error-handling#error-codes). # Rate Limits (/docs/rate-limits) The API limits workspace requests, and each account's posts and actions. ## API Request Limits [#api-request-limits] Limits apply to the whole workspace. Every API key, dashboard session and MCP app shares them, so more keys do not raise them. The limit follows the number of connected accounts, as the table shows. See [Pricing](/docs/pricing). | Workspace | Requests per minute | Analytics per second | | --- | --- | --- | | Free, up to 2 accounts | 60 | 6 | | Paid, 3 or more accounts | 600 | 10 | - Analytics endpoints have their own per-second limit, apart from the per-minute one. These are `GET /v1/posts/{id}/analytics`, `GET /v1/posts/{id}/analytics/timeline` and `GET /v1/accounts/{id}/analytics`. - The windows roll. A request counts for 60 seconds, or 1 second on analytics. ## Rate Limit Headers [#rate-limit-headers] Every authenticated response has these headers. | Header | Description | | --- | --- | | `X-RateLimit-Limit` | The window's limit | | `X-RateLimit-Remaining` | Requests left in the window | | `X-RateLimit-Reset` | Unix seconds when the oldest request stops counting | | `Retry-After` | Seconds to wait, only on a `429` | ## Handle 429 Responses [#handle-429-responses] Over the limit, you get `429 RATE_LIMITED` with a `Retry-After` header. ```json { "error": "Rate limit exceeded. Please retry after 12 seconds.", "code": "RATE_LIMITED", "details": { "currentCount": 600, "limit": 600, "retryAfterSeconds": 12 }, "requestId": "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" } ``` `details.retryAfterSeconds` matches `Retry-After`. A `429` request did nothing, so send it again unchanged after the wait. The SDKs throw on every error. This helper waits for `Retry-After` and retries a few times. It gives up on other codes and on waits over 60 seconds, such as a daily limit, and throws the error again. **TypeScript** ```ts import { Configuration, PostsApi, ResponseError } from "@onepostly/sdk"; const postsApi = new PostsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); async function withRetry( call: () => Promise, { maxAttempts = 3, maxWaitSeconds = 60 } = {} ): Promise { for (let attempt = 1; ; attempt++) { try { return await call(); } catch (error) { if (!(error instanceof ResponseError) || error.response.status !== 429) { throw error; } const envelope = await error.response.json().catch(() => null); const waitSeconds = Number( error.response.headers.get("Retry-After") ?? envelope?.details?.retryAfterSeconds ?? 1 ); if ( envelope?.code !== "RATE_LIMITED" || attempt >= maxAttempts || waitSeconds > maxWaitSeconds ) { throw error; } await new Promise((resolve) => setTimeout(resolve, waitSeconds * 1000)); } } } const response = await withRetry(() => postsApi.createPost({ createPostBody: { text: "Release notes are live.", accounts: [{ accountId: "acc_YOUR_X_ACCOUNT_ID" }], }, }) ); console.log(response); ``` **Python** ```python import asyncio import json import os from onepostly import ApiClient, ApiException, Configuration from onepostly.api.posts_api import PostsApi async def with_retry(call, max_attempts=3, max_wait_seconds=60): for attempt in range(1, max_attempts + 1): try: return await call() except ApiException as error: if error.status != 429: raise try: envelope = json.loads(error.body or "{}") except ValueError: envelope = {} header = (error.headers or {}).get("Retry-After") wait_seconds = int( header or envelope.get("details", {}).get("retryAfterSeconds", 1) ) if ( envelope.get("code") != "RATE_LIMITED" or attempt >= max_attempts or wait_seconds > max_wait_seconds ): raise await asyncio.sleep(wait_seconds) async def main(): async with ApiClient( Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) ) as client: posts_api = PostsApi(client) response = await with_retry( lambda: posts_api.create_post( create_post_body={ "text": "Release notes are live.", "accounts": [{"accountId": "acc_YOUR_X_ACCOUNT_ID"}], } ) ) print(response) asyncio.run(main()) ``` ## Publishing Limits [#publishing-limits] Each account can publish 25 posts in any 60 minutes. It can also publish only a set number per day, which depends on the platform. | Platform | Posts per day | | --- | --- | | X | 50 | | Instagram | 100 | | Facebook | 100 | | Threads | 250 | | LinkedIn | 50 | | YouTube | 50 | | TikTok | 50 | | Pinterest | 25 | | Bluesky | 50 | - The daily limit resets at 00:00 UTC. - Only published posts count, not scheduled or failed ones. - A post counts once per account. A request to 3 accounts counts for each. | Post | Over the limit | What to do | | --- | --- | --- | | Published now | `429 RATE_LIMITED`. Nothing is created, for any account | Wait for `Retry-After`, or drop that account | | Scheduled | Ends `failed` with `RATE_LIMITED`. Other accounts are not affected | Create a new post later | A scheduled post's `error.message` says how long to wait. ## Action Limits [#action-limits] Each account can take only so many platform actions in a window, such as replies, likes and messages. These follow the platform's own limits. Threads, for example, allows 1,000 replies in 24 hours. | Request | Over the limit | | --- | --- | | A comment, like, repost, bookmark, delete or message | `429 QUOTA_EXCEEDED`, with no `Retry-After` | | A post | Ends `failed` with `QUOTA_EXCEEDED` | The error message says when to try again. Nothing happened on the platform, and the limit does not affect other accounts. ## Platform Limits [#platform-limits] Platforms set their own limits and do not publish them. When an account hits one, the response or the post shows one of these codes. | Code | Meaning | What to do | | --- | --- | --- | | `RATE_LIMITED` | The platform slowed the account | Wait, then post again | | `QUOTA_EXCEEDED` | An [action limit](#action-limits), or the platform is at capacity | Try again after the time in the message | | `POSTING_LIMIT_REACHED` | TikTok says the account posted too often | Wait before posting again | | `CAPACITY_LIMITED` | TikTok is not taking more direct posts now | Try again in a few hours | | `UPLOAD_LIMIT_EXCEEDED` | The YouTube channel hit its upload limit | Wait for YouTube's reset | Other codes are in [Error Codes](/docs/error-handling#error-codes). ## Best Practices [#best-practices] - Slow down before `X-RateLimit-Remaining` reaches `0`. - Send one `POST /v1/posts` with several `accounts`. It is one API request, though publishing limits count per account. - Page with `limit` and `cursor` instead of fetching everything. - Use [webhooks](/docs/webhooks) instead of polling post status. - Spread one account's scheduled posts over the day to stay under the hourly limit. # Automations (/docs/automations) An automation answers a comment or message that has a keyword with a direct message, with no code to write. It works for Instagram accounts and Facebook Pages, and each account can hold up to 20 rules. ## How Automations Work [#how-automations-work] A rule's `kind` sets what it answers and how. | `kind` | Runs on | Sends | | --- | --- | --- | | `comment_to_dm` | A comment on the account's posts | A [private reply](/docs/comments#send-a-private-reply) | | `story_reply` | A message with an attachment, such as a story reply | A direct message | | `welcome_dm` | Any message to the account | A direct message | A rule runs when it is `enabled`, the text has one of its `keywords`, and none of its `excludeKeywords`. Matching ignores case. Keywords also match inside longer words, so `guide` matches "Guidelines". To skip those, add `guidelines` to `excludeKeywords`. | Rule | Detail | | --- | --- | | One answer | When several rules match, the oldest answers | | Comments | Each comment is answered once, on any of the account's posts | | Messages | A message rule answers a person at most once per 24 hours | | Platform rules | One private reply per comment, within 7 days. Messages follow the [24-hour window](/docs/inbox#send-a-message) | | Message limits | Over the account's limit, rules send nothing | | Account status | Rules pause until you [reconnect](/docs/account-status#reconnect-an-account) | ## Create an Automation [#create-an-automation] `POST /v1/automations` creates a rule and returns `201`. **TypeScript** ```typescript import { Configuration, AutomationsApi } from "@onepostly/sdk"; const automationsApi = new AutomationsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await automationsApi.createAutomation({ createAutomationBody: { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "kind": "comment_to_dm", "name": "Free guide giveaway", "keywords": [ "guide", "free" ], "excludeKeywords": [ "guidelines" ], "message": "Thanks for your interest! Here is your guide." }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.automations_api import AutomationsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: automations_api = AutomationsApi(api_client) response = await automations_api.create_automation( create_automation_body={ "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "kind": "comment_to_dm", "name": "Free guide giveaway", "keywords": [ "guide", "free" ], "excludeKeywords": [ "guidelines" ], "message": "Thanks for your interest! Here is your guide." }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/automations" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "kind": "comment_to_dm", "name": "Free guide giveaway", "keywords": [ "guide", "free" ], "excludeKeywords": [ "guidelines" ], "message": "Thanks for your interest! Here is your guide." }' ``` **Response** ```json { "id": "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "name": "Free guide giveaway", "kind": "comment_to_dm", "keywords": [ "guide", "free" ], "excludeKeywords": [ "guidelines" ], "message": "Thanks for your interest! Here is your guide.", "enabled": true } ``` | Field | Rule | | --- | --- | | `accountId` | An Instagram or Facebook account from [List Accounts](/docs/connection#list-accounts) | | `kind` | `comment_to_dm`, `story_reply` or `welcome_dm` | | `name` | 1 to 120 characters | | `keywords` | 1 to 20 words, each up to 200 characters | | `excludeKeywords` | Optional, up to 20 words of 200 characters | | `message` | The message to send, 1 to 1,000 characters | | `enabled` | Optional, default `true`. `false` creates it paused | The response holds the new rule's `aut_` id and all of its fields. `excludeKeywords` comes back as `[]` when you leave it out. ## Manage Automations [#manage-automations] | Method | Path | Does | | --- | --- | --- | | `GET` | `/v1/automations` | Lists rules, filtered by `accountId` if sent | | `GET` | `/v1/automations/{id}` | Gets one rule | | `PATCH` | `/v1/automations/{id}` | Changes `name`, `keywords`, `excludeKeywords`, `message` or `enabled` | | `DELETE` | `/v1/automations/{id}` | Deletes the rule and returns `204` | The list groups rules by account, oldest first, 50 per page, up to 100 with `limit`. `PATCH` changes only the fields you send. `kind` and `accountId` cannot change, so create a new rule instead. Disconnecting an account also removes all of its rules. ## Webhooks [#webhooks] Automations send no event of their own. The trigger still arrives as `comment.received` or `message.received`, and a sent message as `message.sent`. See [Comment Webhooks](/docs/webhooks/comments) and [Inbox Webhooks](/docs/webhooks/inbox). ## Errors [#errors] | Code | HTTP | Cause | Fix | |---|---|---|---| | `VALIDATION_ERROR` | 400 | A field is missing or out of range | Fix the field in `param` | | `UNSUPPORTED_PLATFORM` | 400 | Not an Instagram or Facebook account | Use one of those | | `LIMIT_REACHED` | 400 | The account has 20 rules | Delete one first | | `ACCOUNT_NOT_FOUND` | 404 | No such account | Use an id from [List Accounts](/docs/connection#list-accounts) | | `NOT_FOUND` | 404 | No rule has this id | Check the `aut_` id | | `CONFLICT` | 409 | The rules changed during the request | Send it again | Other codes are in [Error Codes](/docs/error-handling#error-codes). # Comments (/docs/comments) Read and answer the comments on your posts, as the account that published them. This also works for [posts made outside Onepostly](/docs/publishing#posts-made-outside-onepostly). ## Support by Platform [#support-by-platform] | Platform | List, comment and reply | Delete | Hide | Like a comment | Private reply | | ---------------------------- | ----------------------- | ------ | ---- | -------------- | ------------- | | [X (Twitter)](/docs/x) | Yes | Yes | No | No | No | | [Instagram](/docs/instagram) | Yes | Yes | Yes | No | Yes | | [Facebook](/docs/facebook) | Yes | Yes | Yes | Yes | Yes | | [Threads](/docs/threads) | Yes | Yes | Yes | No | No | | [LinkedIn](/docs/linkedin) | No | No | No | No | No | | [YouTube](/docs/youtube) | Yes | Yes | No | No | No | | [TikTok](/docs/tiktok) | No | No | No | No | No | | [Pinterest](/docs/pinterest) | No | No | No | No | No | | [Bluesky](/docs/bluesky) | Yes | Yes | No | No | No | An unsupported action returns `400 UNSUPPORTED_PLATFORM`. Each platform page lists its rules, such as [Instagram](/docs/instagram#engagement). On X, comment reads and writes are paid from your [wallet](/docs/pricing#x-wallet). A low balance returns `402 INSUFFICIENT_WALLET`. ## Comment Ids [#comment-ids] Every comment has a `cmt_` id for replying, deleting, hiding, liking and private replies. It works only in the workspace that received it. | Field | Contains | |---|---| | `id` | The `cmt_` id | | `postId` | The post's `pst_` id | | `accountId` | The post's account, which also writes your comments | | `platformCommentId` | The comment's platform id | | `parentId` | The `cmt_` id it replies to, or `null` | | `text` | The comment text | | `username` | The author's username without `@`, or `null` | | `likeCount` | Likes, or `null` when not reported | | `createdAt` | When it was posted, or `null` when not reported | | `replies` | Replies, on platforms that return them | ## List Comments [#list-comments] `GET /v1/posts/{id}/comments` reads comments live from the platform, 50 per page at most. Pass `nextCursor` as `cursor` until `hasMore` is `false`. **TypeScript** ```typescript import { Configuration, CommentsApi } from "@onepostly/sdk"; const commentsApi = new CommentsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await commentsApi.listComments({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", limit: 25, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.comments_api import CommentsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: comments_api = CommentsApi(api_client) response = await comments_api.list_comments( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", limit=25, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/comments?limit=25" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "cmt_amtpCkVartn0nqaE1Je0v2VkSEm03WARoWPFRyRgiFzkP3uEcxR4W9LztUdBGz2YWD5AFw9KMvsNTqsnW544OSHrpC1iYD3cgpan0HmOMKINUmnERALRze", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "platformCommentId": "17988123456789012", "parentId": null, "text": "Great results, congrats!", "username": "mark.builds", "likeCount": 0, "createdAt": "2027-03-15T09:42:19.000Z", "replies": [] }, { "id": "cmt_cDQEpthzkh9NCjzItFNd19ItnVdYlB4tB4t92XY6Edv1B72jDW9DvSpwIgqi6O75UgGzjUt3zONixH1SGrdIkBYuTm34IsLyxwSJLHBgdYz5DYn31g4zQ0", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "platformCommentId": "18050512345678901", "parentId": null, "text": "Love this! Where can I get one?", "username": "jane_doe", "likeCount": 3, "createdAt": "2027-03-15T09:20:11.000Z", "replies": [ { "id": "cmt_8c86vC3o0CyUONgnTCe2CNWfzeYcEfSNcRGHQeDTlVL6dsCpsa0OptpfZ9BoWxAPeFYf82BGoYyBMqDIOfv3NcCyj5R6TP7RcXGj8OcZEOBnRYy4q42spq", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "platformCommentId": "18050598765432109", "parentId": "cmt_cDQEpthzkh9NCjzItFNd19ItnVdYlB4tB4t92XY6Edv1B72jDW9DvSpwIgqi6O75UgGzjUt3zONixH1SGrdIkBYuTm34IsLyxwSJLHBgdYz5DYn31g4zQ0", "text": "The link is in our bio!", "username": "yourbrand", "likeCount": 1, "createdAt": "2027-03-15T09:24:37.000Z", "replies": [] } ] } ], "nextCursor": "QVFIUjRtc2N5ZAWZAkV3ZA0bHBpTlJXNWdVaU5GUEI3c1BtX0VnSzFnYWZAkdC1QWFZAiR0Q5ZAVNfNlBhTHVoa2RnMEtsSVlyTkhz", "hasMore": true } ``` A post that is not live yet returns `409 NOT_PUBLISHED`, so wait for `post.published`. Stories have no comments. ## Comment on a Post [#comment-on-a-post] `POST /v1/posts/{id}/comments` with `text` comments as the post's account and returns `201`. Text over the platform's [limit](/docs/platforms#text-limits) returns `400 TEXT_TOO_LONG`. **TypeScript** ```typescript import { Configuration, CommentsApi } from "@onepostly/sdk"; const commentsApi = new CommentsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await commentsApi.createComment({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", commentTextBody: { "text": "Thanks for watching!" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.comments_api import CommentsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: comments_api = CommentsApi(api_client) response = await comments_api.create_comment( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", comment_text_body={ "text": "Thanks for watching!" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/comments" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Thanks for watching!" }' ``` **Response** ```json { "id": "cmt_jDn7AR68Du8FrawkvedZhy5qdVdXf8RMwWvtDCyDlOrDKhCBUKiix6E0T0FqW3UCGizpXZkVbUZ5b3uBVb8DDqwU0wRr4eoefhlGX0uQc6y2iCPDboTCpG", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "platformCommentId": "18063456789012345", "parentId": null, "text": "Thanks for watching!", "username": null, "likeCount": 0, "createdAt": "2027-03-15T10:00:00.000Z", "replies": [] } ``` ## Reply to a Comment [#reply-to-a-comment] `POST /v1/comments/{id}/replies` with `text` returns `201` with the reply. Its `parentId` is the comment you answered. **TypeScript** ```typescript import { Configuration, CommentsApi } from "@onepostly/sdk"; const commentsApi = new CommentsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await commentsApi.replyToComment({ id: "cmt_YOUR_COMMENT_ID", commentTextBody: { "text": "Glad you liked it." }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.comments_api import CommentsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: comments_api = CommentsApi(api_client) response = await comments_api.reply_to_comment( "cmt_YOUR_COMMENT_ID", comment_text_body={ "text": "Glad you liked it." }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/comments/cmt_YOUR_COMMENT_ID/replies" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Glad you liked it." }' ``` **Response** ```json { "id": "cmt_ztfnHfaU0iNb9UBUuNnnxN8waYgVvu3Y12mVBDR6dweXoMSb4tn0DeDwvC0IeIW2SQEWLo9bNYoYFOPhESI4pxuKjN5txdk2pDjSaIaePIKjvOpsFJ26lA", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "platformCommentId": "18063456789012399", "parentId": "cmt_YOUR_COMMENT_ID", "text": "Glad you liked it.", "username": null, "likeCount": 0, "createdAt": "2027-03-15T10:00:00.000Z", "replies": [] } ``` ## Delete a Comment [#delete-a-comment] `DELETE /v1/comments/{id}` deletes a comment and returns `204`. On X, Instagram, Facebook and Threads, the id of one of your own posts returns `400 NOT_A_COMMENT`. Use [Delete a Post](/docs/post-lifecycle#delete-a-post) instead. ## Hide or Unhide a Comment [#hide-or-unhide-a-comment] `PUT /v1/comments/{id}/hidden` hides a comment from everyone but its author. `DELETE` on the same path shows it again. Both return `id` and `hidden`. It works on Instagram, Facebook and Threads only. ## Like a Comment [#like-a-comment] `PUT /v1/comments/{id}/like` likes a comment as the Page. `DELETE` on the same path removes the like. Both return `id` and `liked`. Facebook only. ## Send a Private Reply [#send-a-private-reply] `POST /v1/comments/{id}/private-reply` sends the author a direct message. It returns `201` with the message `id`, `commentId`, `text` and `createdAt`. **TypeScript** ```typescript import { Configuration, CommentsApi } from "@onepostly/sdk"; const commentsApi = new CommentsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await commentsApi.sendPrivateReply({ id: "cmt_YOUR_COMMENT_ID", privateReplyBody: { "text": "Thanks! Check your DMs." }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.comments_api import CommentsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: comments_api = CommentsApi(api_client) response = await comments_api.send_private_reply( "cmt_YOUR_COMMENT_ID", private_reply_body={ "text": "Thanks! Check your DMs." }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/comments/cmt_YOUR_COMMENT_ID/private-reply" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Thanks! Check your DMs." }' ``` **Response** ```json { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM3NjE5NzM2Mzg3MTI4", "commentId": "cmt_YOUR_COMMENT_ID", "text": "Thanks! Check your DMs.", "createdAt": "2027-03-15T10:00:00.000Z" } ``` | Rule | Instagram | Facebook | |---|---|---| | `text` length | 1,000 characters | 2,000 characters | | Replies per comment | 1 | 1 | | Time limit | 7 days | 7 days | A second reply, or one after 7 days, fails with `502 PRIVATE_REPLY_FAILED`. After the private reply, the conversation continues in the [Inbox](/docs/inbox). To answer keywords without writing any code, set up an [automation](/docs/automations). ## Webhooks [#webhooks] | Event | Fires when | |---|---| | `comment.created` | You comment or reply through the API | | `comment.deleted` | You delete a comment, or it is removed on Facebook | | `comment.received` | Anyone comments on an Instagram or Facebook post | Hides, likes and private replies send no event. See [Comment Webhooks](/docs/webhooks/comments). ## Errors [#errors] | Code | HTTP | Cause | Fix | |---|---|---|---| | `NOT_FOUND` | 404 | No post or comment has this id | Check the id | | `UNSUPPORTED_PLATFORM` | 400 | The platform lacks this action | See [Support by Platform](#support-by-platform) | | `TEXT_TOO_LONG` | 400 | `text` is over the [limit](/docs/platforms#text-limits) | Shorten it | | `NOT_A_COMMENT` | 400 | The id is one of your posts | Use [Delete a Post](/docs/post-lifecycle#delete-a-post) | | `NOT_PUBLISHED` | 409 | The post is not live yet | Wait for `post.published` | | `TOKEN_EXPIRED`, `TOKEN_INVALID` | 409 | The account's access ended | [Reconnect it](/docs/account-status#reconnect-an-account) | | `INSUFFICIENT_WALLET` | 402 | The wallet is too low for an X action | Top up, then retry | | `COMMENTS_PERMISSION` | 422 | A permission is missing, the delete is refused, or comments are off | Reconnect and approve every permission | | `COMMENT_*_FAILED`, `PRIVATE_REPLY_FAILED` | 502 | The platform did not complete it | Read `error`, then retry later | Comments, replies, deletes and private replies count toward [action limits](/docs/rate-limits#action-limits). Over one, you get `429 QUOTA_EXCEEDED`, and `error` says when to retry. `429 RATE_LIMITED` is the [request limit](/docs/rate-limits#handle-429-responses). Other codes are in [Error Codes](/docs/error-handling#error-codes). # Likes and Reposts (/docs/engagement) As a connected account, like, repost and bookmark its own posts or any post it can see, and list who reposted a post. For comments, see [Comments](/docs/comments). To quote a post, create a new post with `quotePostId`, as [Threads, Replies and Quotes](/docs/replies-and-quotes) explains. ## Support by Platform [#support-by-platform] | Platform | Like | Repost | Bookmark | List reposters | |---|---|---|---|---| | [X (Twitter)](/docs/x) | Yes | Yes | Yes | Yes | | [Facebook](/docs/facebook) | Yes | No | No | No | | [Threads](/docs/threads) | No | Yes | No | No | | [YouTube](/docs/youtube) | Yes | No | No | No | | [Bluesky](/docs/bluesky) | Yes | Yes | Yes | Yes | Instagram, LinkedIn, TikTok and Pinterest support none of these actions, so they return `400 UNSUPPORTED_PLATFORM`. Each platform's own rules are in its Engagement section, such as the one for [X](/docs/x#engagement). On X, every action, undo and reposter read is paid from your [wallet](/docs/pricing#x-wallet). A low balance returns `402 INSUFFICIENT_WALLET`. ## Likes, Reposts and Bookmarks [#likes-reposts-and-bookmarks] Each action runs as the account in the path. `PUT` takes the action and `DELETE` undoes it. Both return `200` with the action's state field. | Action | Path | State field | |---|---|---| | Like | `/v1/accounts/{id}/likes/{postId}` | `liked` | | Bookmark | `/v1/accounts/{id}/bookmarks/{postId}` | `bookmarked` | | Repost | `/v1/accounts/{id}/reposts/{postId}` | `reposted` | **TypeScript** ```typescript import { Configuration, EngagementApi } from "@onepostly/sdk"; const engagementApi = new EngagementApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await engagementApi.likePost({ id: "acc_YOUR_X_ACCOUNT_ID", postId: "1960956321831854280", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.engagement_api import EngagementApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: engagement_api = EngagementApi(api_client) response = await engagement_api.like_post( "acc_YOUR_X_ACCOUNT_ID", "1960956321831854280", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X PUT "https://api.onepostly.com/v1/accounts/acc_YOUR_X_ACCOUNT_ID/likes/1960956321831854280" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "liked": true } ``` ### Name the Post [#name-the-post] | `postId` | Use it for | |---|---| | A `pst_` id | The account's own posts. Another account's returns `400 POST_ACCOUNT_MISMATCH` | | The platform's id | Any post the account can see. Percent-encode it, as the SDKs do | A Bluesky `at://` URI is sent as `at%3A%2F%2F…`. ### Response [#response] | Field | Contains | |---|---| | `postId` | The post's `pst_` id, even when you sent a platform id. Either undoes it | | `accountId` | The account that acted | | `platform` | The account's platform | | `liked`, `bookmarked` or `reposted` | `true` after the action, `false` after the undo | | `platformRepostId` | Reposts only. The repost's platform id, or `null` | ## Repeating a Request [#repeating-a-request] Every `PUT` and `DELETE` goes to the platform, so a repeat is safe. - On Bluesky, a repeated `PUT` keeps one like or repost. - On X, each request is charged, repeats included. - Each success sends its own [webhook event](#webhooks), repeats included. These actions count toward [action limits](/docs/rate-limits#action-limits). Going over one returns `429 QUOTA_EXCEEDED`, and `error` says when to retry. ## Undo a Threads Repost [#undo-a-threads-repost] On Threads, you can only undo a repost made through Onepostly, of a post published through Onepostly. Any other undo returns `400 UNREPOST_REQUIRES_REPOST_ID`. Undo those in the Threads app. ## List Reposters [#list-reposters] `GET /v1/posts/{id}/reposts` lists who reposted a post, on X and Bluesky. Each page holds 50 by default, or up to 100 with `limit`. Pass `nextCursor` as `cursor` until `hasMore` is `false` to read them all. **TypeScript** ```typescript import { Configuration, EngagementApi } from "@onepostly/sdk"; const engagementApi = new EngagementApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await engagementApi.listReposters({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.engagement_api import EngagementApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: engagement_api = EngagementApi(api_client) response = await engagement_api.list_reposters( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/reposts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "1458203917345619968", "username": "jane_doe", "displayName": "Jane Doe", "avatarUrl": "https://pbs.twimg.com/profile_images/1683325380441128960/yRsRRjGO_normal.jpg" }, { "id": "897451236985471234", "username": "mark_builds", "displayName": "Mark Builds", "avatarUrl": "https://pbs.twimg.com/profile_images/1702113548720128000/Qm4sXk1p_normal.jpg" } ], "nextCursor": null, "hasMore": false } ``` Each entry has the platform `id`, the `username` without `@`, the `displayName` and the `avatarUrl`. The last three can be `null`. ## Webhooks [#webhooks] | Action | Webhook event | |---|---| | Like or unlike | `engagement.liked`, `engagement.unliked` | | Bookmark or remove it | `engagement.bookmarked`, `engagement.unbookmarked` | | Repost or undo it | `engagement.reposted`, `engagement.unreposted` | These events fire only for actions you take through the API, not when other people like or repost your posts. See [Engagement Webhooks](/docs/webhooks/engagement). ## Errors [#errors] | Code | HTTP | Cause | Fix | |---|---|---|---| | `ACCOUNT_NOT_FOUND`, `NOT_FOUND` | 404 | No such account or `pst_` post | Use ids from [List Accounts](/docs/connection#list-accounts) and your posts | | `UNSUPPORTED_PLATFORM` | 400 | The platform lacks this action | See [Support by Platform](#support-by-platform) | | `POST_ACCOUNT_MISMATCH` | 400 | The `pst_` id is another account's post | Act as that account, or use the platform id | | `UNREPOST_REQUIRES_REPOST_ID` | 400 | This [Threads repost](#undo-a-threads-repost) cannot be undone here | Undo it in the Threads app | | `INSUFFICIENT_WALLET` | 402 | The wallet is too low for an X action | Top up, then retry | | `NOT_PUBLISHED` | 409 | The post is not live yet | Wait for `post.published` | | `TOKEN_EXPIRED`, `TOKEN_INVALID`, `CONNECTION_INACTIVE` | 409 | The account needs a reconnect | [Reconnect it](/docs/account-status#reconnect-an-account) | | `ENGAGEMENT_PERMISSION`, `REPOST_PERMISSION`, `UNREPOST_PERMISSION` | 422 | A permission is missing, or the post does not allow it | Reconnect and approve every permission | | `ENGAGEMENT_FAILED`, `REPOST_FAILED`, `UNREPOST_FAILED` | 502 | The platform did not complete it | Read `error`, then retry later | Other codes are in [Error Codes](/docs/error-handling#error-codes). # Inbox (/docs/inbox) Read and answer an account's direct messages, start conversations, and send buttons, quick replies and cards. Messages are read live from the platform. ## Support by Platform [#support-by-platform] | Feature | [Instagram](/docs/instagram#inbox) | [Facebook](/docs/facebook#inbox) | [Bluesky](/docs/bluesky#inbox) | |---|---|---|---| | List and read | Yes | Yes | Yes | | Start a conversation with | Username or user id | Page-scoped id | Handle or DID | | Message length | 1,000 characters | 2,000 characters | 1,000 graphemes | | Sending window | 24 hours | 24 hours | None | | [Rich messages](#rich-messages) | Yes | Yes | No | | Received attachments | Yes | Yes | No | | Ice breakers and menu | No | Yes | No | | Inbox webhooks | Yes | Yes | No | | [Private replies](/docs/comments#send-a-private-reply), [automations](/docs/automations) | Yes | Yes | No | Other platforms return `400 UNSUPPORTED_PLATFORM`. The account needs messaging access, approved at connect. Without it you get `422 INBOX_PERMISSION`, so reconnect and approve every permission. On Bluesky, the App Password needs [direct message access](/docs/connection#connect-bluesky). ## List Conversations [#list-conversations] `GET /v1/accounts/{id}/conversations` lists conversations, newest first. Each page holds 50 by default, or up to 100 with `limit`. Pass `nextCursor` as `cursor` until `hasMore` is `false` to read them all. **TypeScript** ```typescript import { Configuration, InboxApi } from "@onepostly/sdk"; const inboxApi = new InboxApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await inboxApi.listConversations({ id: "acc_YOUR_INSTAGRAM_ACCOUNT_ID", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.inbox_api import InboxApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: inbox_api = InboxApi(api_client) response = await inbox_api.list_conversations( "acc_YOUR_INSTAGRAM_ACCOUNT_ID", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_INSTAGRAM_ACCOUNT_ID/conversations" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "cnv_u1rTltEvz7pEbzpQOLjQAlMVsqWCdakS9U2wjAFB6CV6SYgY3Bx8GTrVhAn9njOg3eB2YWHX", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "members": [ { "id": "17841401234567890", "username": "yourbrand", "displayName": "yourbrand" }, { "id": "6873452198765432", "username": "jane_doe", "displayName": "jane_doe" } ], "muted": false, "unreadCount": 0, "lastMessage": { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM2NDEyOTg3NjU0MzIxMDk4NzY1NDMy", "text": "Do you ship to Canada?", "sentAt": "2027-03-15T11:42:08.000Z" } }, { "id": "cnv_UYeVH71CtvWwPasNAhEA9WXmVPAMJhQLmnGMapF5MxmPu59aNUBxoHt0T0YnAq98AujCL19c", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "members": [ { "id": "17841401234567890", "username": "yourbrand", "displayName": "yourbrand" }, { "id": "7120984456321987", "username": "mark.builds", "displayName": "mark.builds" } ], "muted": false, "unreadCount": 0, "lastMessage": { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM1MzQ1Njc4OTAxMjM0NTY3ODkwMTIz", "text": "Thanks, it arrived today!", "sentAt": "2027-03-15T10:17:45.000Z" } } ], "nextCursor": null, "hasMore": false } ``` | Field | Contains | |---|---| | `id` | The `cnv_` id | | `accountId` | The conversation's account | | `members` | Each person's platform `id`, `username` and `displayName`, the last two `null` when hidden | | `muted` | `true` when muted. Bluesky only | | `unreadCount` | Unread messages, or `0` when not reported | | `lastMessage` | The newest message's `id`, `text` and `sentAt`, or `null` | `GET /v1/accounts/{id}/conversations/{conversationId}` returns a single conversation, with the same fields as the list. ### Conversation Ids [#conversation-ids] A `cnv_` id works only in the workspace that received it. On Instagram and Facebook, one conversation can have two ids. List Conversations returns one, and [Start a Conversation](#start-a-conversation) and [webhooks](/docs/webhooks/inbox) return the other. Both work. ## Read Messages [#read-messages] `GET /v1/accounts/{id}/conversations/{conversationId}/messages` lists messages, newest first. Paging works the same as for conversations. **TypeScript** ```typescript import { Configuration, InboxApi } from "@onepostly/sdk"; const inboxApi = new InboxApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await inboxApi.listMessages({ id: "acc_YOUR_INSTAGRAM_ACCOUNT_ID", conversationId: "cnv_YOUR_CONVERSATION_ID", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.inbox_api import InboxApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: inbox_api = InboxApi(api_client) response = await inbox_api.list_messages( "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "cnv_YOUR_CONVERSATION_ID", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_INSTAGRAM_ACCOUNT_ID/conversations/cnv_YOUR_CONVERSATION_ID/messages" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM2NDEyOTg3NjU0MzIxMDk4NzY1NDMy", "conversationId": "cnv_YOUR_CONVERSATION_ID", "text": "Do you ship to Canada?", "senderId": "6873452198765432", "sentAt": "2027-03-15T11:42:08.000Z", "attachments": [] }, { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM2NDEyOTg3NjU0MzIxMDk4NzY1NDE5", "conversationId": "cnv_YOUR_CONVERSATION_ID", "text": "Yes, it is in stock in every size.", "senderId": "17841401234567890", "sentAt": "2027-03-15T11:40:02.000Z", "attachments": [] }, { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM2NDEyOTg3NjU0MzIxMDk4NzY1NDA3", "conversationId": "cnv_YOUR_CONVERSATION_ID", "text": "Hi! Is this jacket still available?", "senderId": "6873452198765432", "sentAt": "2027-03-15T11:38:40.000Z", "attachments": [] }, { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM2NDEyOTg3NjU0MzIxMDk4NzY1Mzk1", "conversationId": "cnv_YOUR_CONVERSATION_ID", "text": null, "senderId": "6873452198765432", "sentAt": "2027-03-15T11:38:15.000Z", "attachments": [ { "type": "image", "url": "https://lookaside.fbsbx.com/ig_messaging_cdn/?asset_id=18043219876543210&signature=AbxQ3kLm9pRtYv2WcZ8sN1" } ] } ], "nextCursor": null, "hasMore": false } ``` | Field | Contains | |---|---| | `id` | The message's platform id | | `conversationId` | The message's conversation | | `text` | The text, or `null` for attachments only or a deleted Bluesky message | | `senderId` | An Instagram-scoped id, a Page-scoped id or a Bluesky DID | | `sentAt` | When it was sent, or `null` | | `attachments` | Each with a `type` and a direct `url`. Empty on Bluesky | An attachment `type` is `image`, `video`, `audio`, `file` or `other`. ## Start a Conversation [#start-a-conversation] `POST /v1/accounts/{id}/conversations` with a `recipient` starts a one-to-one conversation with that person and returns `201`. **TypeScript** ```typescript import { Configuration, InboxApi } from "@onepostly/sdk"; const inboxApi = new InboxApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await inboxApi.createConversation({ id: "acc_YOUR_BLUESKY_ACCOUNT_ID", createConversationBody: { "recipient": "alice.bsky.social" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.inbox_api import InboxApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: inbox_api = InboxApi(api_client) response = await inbox_api.create_conversation( "acc_YOUR_BLUESKY_ACCOUNT_ID", create_conversation_body={ "recipient": "alice.bsky.social" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts/acc_YOUR_BLUESKY_ACCOUNT_ID/conversations" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "recipient": "alice.bsky.social" }' ``` **Response** ```json { "id": "cnv_xZWwUFsb6q2nrlD7GUiqQxNHfiqbgdNAjqlcvDLTpafW1UHpqYkJAIRnqf5uJ71zS3gigSZp", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "members": [ { "id": "did:plc:4y7hqd2kz3rbe6mfxw5tnc2a", "username": "yourbrand.bsky.social", "displayName": "Your Brand" }, { "id": "did:plc:z72i7hdynmk6r22z27h6tvur", "username": "alice.bsky.social", "displayName": "Alice" } ], "muted": false, "unreadCount": 0, "lastMessage": null } ``` | Platform | `recipient` | Notes | |---|---|---| | Instagram | A username, `@` optional, or a numeric user id | Usernames work for public Business and Creator accounts. Otherwise use a `senderId` | | Facebook | A numeric Page-scoped id | Find it in `members` or a `senderId` | | Bluesky | A handle, `@` optional, or a DID | An existing conversation comes back as is | On Instagram and Facebook, a new conversation is readable once it has a message. Until then you get `404 CONVO_NOT_FOUND` and no messages. The person must have written in the last 24 hours, or sending fails with `409 MESSAGE_WINDOW_EXPIRED`. On Bluesky, the recipient's settings decide, and follow-only settings or a block return `409 RECIPIENT_UNREACHABLE`. ## Send a Message [#send-a-message] `POST /v1/accounts/{id}/conversations/{conversationId}/messages` sends a message and returns `201`. `text` is required and must fit the [message length](#support-by-platform). **TypeScript** ```typescript import { Configuration, InboxApi } from "@onepostly/sdk"; const inboxApi = new InboxApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await inboxApi.sendMessage({ id: "acc_YOUR_FACEBOOK_ACCOUNT_ID", conversationId: "cnv_YOUR_CONVERSATION_ID", sendMessageBody: { "text": "Yes, we deliver on Sundays from 10:00 to 14:00." }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.inbox_api import InboxApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: inbox_api = InboxApi(api_client) response = await inbox_api.send_message( "acc_YOUR_FACEBOOK_ACCOUNT_ID", "cnv_YOUR_CONVERSATION_ID", send_message_body={ "text": "Yes, we deliver on Sundays from 10:00 to 14:00." }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/conversations/cnv_YOUR_CONVERSATION_ID/messages" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Yes, we deliver on Sundays from 10:00 to 14:00." }' ``` **Response** ```json { "id": "m_Xq2b7KfRz1nT8vLp3sWcYd9GhJ0aMeU4oQiN5kB6xZtVrHlF2gDsAy7wEcP1uOjI3mK8nL", "conversationId": "cnv_YOUR_CONVERSATION_ID", "text": "Yes, we deliver on Sundays from 10:00 to 14:00.", "senderId": "104987654321098", "sentAt": "2027-03-15T12:05:31.000Z", "attachments": [] } ``` Instagram and Facebook accept messages only within 24 hours of the person's last one, and message tags are not available. After the window closes, you get `409 MESSAGE_WINDOW_EXPIRED` until they write again. Messages count toward [action limits](/docs/rate-limits#action-limits). Over one, you get `429 QUOTA_EXCEEDED`, and `error` says when to retry. A platform slowdown returns `429 RATE_LIMITED`. ## Rich Messages [#rich-messages] On Instagram and Facebook, these fields add something to open or tap. Bluesky returns `400 ATTACHMENT_UNSUPPORTED` or `400 TEMPLATE_UNSUPPORTED`. | Field | Adds | Limits | |---|---|---| | `attachmentUrl` | An image, video, audio or PDF | Public HTTPS, up to 2,048 characters | | `quickReplies` | Tappable replies | Up to 13 | | `buttons` | Buttons under the text | Up to 3 | | `cards` | A swipeable carousel | Up to 10, each with up to 3 `buttons` | | Item | Fields | |---|---| | Quick reply | `title` up to 20 characters, `payload` up to 1,000, optional `imageUrl` | | Button | `type`, `title` up to 20 characters, and `url` for `web_url` or `payload` for `postback` | | Card | `title` and optional `subtitle` up to 80 characters, optional `imageUrl` and `buttons` | **TypeScript** ```typescript import { Configuration, InboxApi } from "@onepostly/sdk"; const inboxApi = new InboxApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await inboxApi.sendMessage({ id: "acc_YOUR_FACEBOOK_ACCOUNT_ID", conversationId: "cnv_YOUR_CONVERSATION_ID", sendMessageBody: { "text": "Which pickup time works for you?", "quickReplies": [ { "title": "Morning", "payload": "PICKUP_AM" }, { "title": "Afternoon", "payload": "PICKUP_PM" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.inbox_api import InboxApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: inbox_api = InboxApi(api_client) response = await inbox_api.send_message( "acc_YOUR_FACEBOOK_ACCOUNT_ID", "cnv_YOUR_CONVERSATION_ID", send_message_body={ "text": "Which pickup time works for you?", "quickReplies": [ { "title": "Morning", "payload": "PICKUP_AM" }, { "title": "Afternoon", "payload": "PICKUP_PM" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/conversations/cnv_YOUR_CONVERSATION_ID/messages" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Which pickup time works for you?", "quickReplies": [ { "title": "Morning", "payload": "PICKUP_AM" }, { "title": "Afternoon", "payload": "PICKUP_PM" } ] }' ``` **Response** ```json { "id": "m_Rk5nW8cTq2vYb7LzP4sXdA1fGh9JmE3oUiK6tN0aBwVyQ2rHlC8gDsMx5eFpZ1uOjI7kL4", "conversationId": "cnv_YOUR_CONVERSATION_ID", "text": "Which pickup time works for you?", "senderId": "104987654321098", "sentAt": "2027-03-15T12:06:10.000Z", "attachments": [] } ``` A message has one main part, and `text` is always required. | You send | The person sees | |---|---| | `attachmentUrl` | The attachment only | | `cards` | The carousel only, without outside `buttons` | | `buttons` | The text, cut at 640 characters, with buttons | | Only `text` | The text | `quickReplies` go with any of these, but `attachmentUrl` together with `buttons` or `cards` in one message returns `400 INVALID_TEMPLATE`. The `attachmentUrl` extension sets how it is sent. | Extension | Sent as | |---|---| | `.mp4`, `.mov`, `.m4v`, `.webm`, `.avi` | Video | | `.mp3`, `.m4a`, `.aac`, `.wav` | Audio | | `.pdf` | File | | Anything else | Image | | Tapped | You receive | |---|---| | A quick reply | `message.received` with the `title` as `text`. Match on it, since `payload` is not sent | | A `postback` button | `message.postback` with its `payload` | | A `web_url` button | Nothing. The link opens | ## Messenger Profile [#messenger-profile] A Facebook Page can greet people with up to 4 ice breaker questions in a new chat, and keep a menu of up to 3 items in every chat. `GET /v1/accounts/{id}/messenger-profile` returns the setup. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.getMessengerProfile({ id: "acc_YOUR_FACEBOOK_ACCOUNT_ID", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.get_messenger_profile( "acc_YOUR_FACEBOOK_ACCOUNT_ID", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/messenger-profile" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "iceBreakers": [ { "question": "What are your opening hours?", "payload": "HOURS" }, { "question": "Do you deliver?", "payload": "DELIVERY" } ], "persistentMenu": [ { "type": "web_url", "title": "Order online", "url": "https://example.com/order", "payload": null } ] } ``` `PUT` on the same path changes it. Send `iceBreakers`, `persistentMenu` or both. Fields you leave out stay. The response is the setup after the change. | Field | Each item | Limits | |---|---|---| | `iceBreakers` | `question` and `payload` | Up to 4. `question` up to 80 characters, `payload` up to 1,000 | | `persistentMenu` | `type`, `title`, and `url` or `payload` | Up to 3. `title` up to 20 characters | A `web_url` item needs `url`, and a `postback` item needs `payload`. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.setMessengerProfile({ id: "acc_YOUR_FACEBOOK_ACCOUNT_ID", setMessengerProfileBody: { "iceBreakers": [ { "question": "What are your opening hours?", "payload": "HOURS" }, { "question": "Do you deliver?", "payload": "DELIVERY" } ], "persistentMenu": [ { "type": "web_url", "title": "Order online", "url": "https://example.com/order" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.set_messenger_profile( "acc_YOUR_FACEBOOK_ACCOUNT_ID", set_messenger_profile_body={ "iceBreakers": [ { "question": "What are your opening hours?", "payload": "HOURS" }, { "question": "Do you deliver?", "payload": "DELIVERY" } ], "persistentMenu": [ { "type": "web_url", "title": "Order online", "url": "https://example.com/order" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X PUT "https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/messenger-profile" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "iceBreakers": [ { "question": "What are your opening hours?", "payload": "HOURS" }, { "question": "Do you deliver?", "payload": "DELIVERY" } ], "persistentMenu": [ { "type": "web_url", "title": "Order online", "url": "https://example.com/order" } ] }' ``` **Response** ```json { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "iceBreakers": [ { "question": "What are your opening hours?", "payload": "HOURS" }, { "question": "Do you deliver?", "payload": "DELIVERY" } ], "persistentMenu": [ { "type": "web_url", "title": "Order online", "url": "https://example.com/order", "payload": null } ] } ``` Tapping an ice breaker or `postback` item sends `message.postback` with its `payload`. Other account types return `400 UNSUPPORTED_PLATFORM`. ## Webhooks [#webhooks] Instagram and Facebook inbox events keep your copy current without polling. | Event | Fires when | |---|---| | `message.received` | Someone messages the account | | `message.sent` | The account sends, here or on the platform | | `message.delivered`, `message.read` | Your messages arrive, or are read | | `message.reaction` | The person adds or removes a reaction | | `message.postback` | The person taps a button, menu item or ice breaker | | `message.deleted` | The person unsends a message, Instagram only | Each event's `conversationId` works with the routes here. See [Inbox Webhooks](/docs/webhooks/inbox). Bluesky sends no events, so list its conversations instead. ## Errors [#errors] | Code | HTTP | Cause | Fix | |---|---|---|---| | `UNSUPPORTED_PLATFORM` | 400 | The platform has no inbox | See [Support by Platform](#support-by-platform) | | `TEXT_REQUIRED`, `TEXT_TOO_LONG` | 400 | `text` is empty or too long | Fit the message length | | `INVALID_TEMPLATE`, `INVALID_ATTACHMENT` | 400 | A bad button, a mixed attachment, or a non-HTTPS URL | Fix the fields in `error` | | `CONVO_NOT_FOUND`, `RECIPIENT_NOT_FOUND` | 404 | No such conversation or recipient | Check the id | | `MESSAGE_WINDOW_EXPIRED` | 409 | The 24-hour window closed | Wait for the person to write | | `RECIPIENT_UNREACHABLE`, `CONVO_LOCKED` | 409 | The person refuses messages, or the Bluesky chat is locked | Reach them another way | | `TOKEN_EXPIRED`, `TOKEN_INVALID`, `CONNECTION_INACTIVE`, `CONNECTION_BROKEN` | 409 | The account needs a reconnect | [Reconnect it](/docs/account-status#reconnect-an-account) | | `INBOX_PERMISSION` | 422 | No messaging access | Reconnect and approve every permission | | `INBOX_FAILED` | 502 | The platform did not complete it | Retry. Reconnect if it keeps failing | Other codes are in [Error Codes](/docs/error-handling#error-codes). # Post Status and Deleting (/docs/post-lifecycle) Each account's post moves through its own statuses. Read the status to know whether a post is live, and delete a live post to remove it from the platform. ## Post Status [#post-status] Get a post with `GET /v1/posts/{id}`. **TypeScript** ```typescript 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); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.get_post( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "source": "onepostly", "status": "published", "text": "New release notes are up.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "104987654321098_122134567890123456", "url": "https://www.facebook.com/yourbrand/posts/pfbid02Xk8c7rFqZJ1nT5sV9wYbLmQe3hGdR6uAoPiK4zCxN2", "error": null, "publishedAt": "2027-03-15T09:00:04.000Z", "metrics": { "impressions": 1234, "reach": 987, "likes": 123, "comments": 12, "shares": 4, "saves": null, "views": 456, "engagement": 139 }, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } ``` | `status` | Meaning | Final | | --- | --- | --- | | `scheduled` | Waiting for `scheduledFor` | No | | `publishing` | On its way to the platform | No | | `published` | Live on the platform | Yes, unless you [delete it](#delete-a-post) | | `failed` | Not published. The reason is in `error` | Yes | | `cancelled` | Cancelled before it was published | Yes | | `deleted` | Removed from the platform | Yes | New statuses can be added, so handle a value you do not know. The posts of one request share a `groupId`, but each has its own status. The X post can be `published` while the Instagram post is `failed`. To get notified instead of checking, use the [post webhooks](/docs/webhooks/posts) such as `post.published` and `post.failed`. ## Failed Posts [#failed-posts] A failed post has an `error` with a `code` and a `message`. ```json { "id": "pst_8b7f2c641e3d4f9ab2c56d0e8a4f1b27", "platform": "instagram", "status": "failed", "platformPostId": null, "url": null, "error": { "code": "MEDIA_UNFETCHABLE", "message": "Could not download media URL (HTTP 403)." } } ``` - A failed post is final. It is not published again, and waiting does not change it. Fix the cause and create a new post for that account. - Build your logic on `error.code`. The `message` is for people and its wording can change. - `PUBLISH_INTERRUPTED` means the outcome is unknown, and the post may be live. Check the account on the platform before you post again. - A failed X post is refunded to the wallet, unless part of its thread went live. The codes are in each platform page's Errors section, such as [X](/docs/x#errors), and in [Error Codes](/docs/error-handling#error-codes). ### Threads That Fail Partway [#threads-that-fail-partway] On X, Threads and Bluesky, a reply of a [thread](/docs/replies-and-quotes) can fail after the first posts went live. The post then ends as `failed`, and its `platformPostId` and `url` point to the first post of the thread. To remove the posts that went live, [delete the post](#delete-a-post). ## Post Links [#post-links] A published post has a `platformPostId`, the platform's own id, and a `url`, its public link. - `url` can be `null` on a published post. On some platforms it fills in a few minutes after publishing. - On TikTok, `platformPostId` and `url` change once TikTok makes the video public. - A post that is not published has `null` for both, except a [thread that failed partway](#threads-that-fail-partway). ## Delete a Post [#delete-a-post] `DELETE /v1/posts/{id}` does what fits the post's status and returns the post. **TypeScript** ```typescript import { Configuration, PostsApi } from "@onepostly/sdk"; const postsApi = new PostsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await postsApi.deletePost({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.delete_post( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X DELETE "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "source": "onepostly", "status": "deleted", "text": "New release notes are up.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "104987654321098_122134567890123456", "url": "https://www.facebook.com/yourbrand/posts/pfbid02Xk8c7rFqZJ1nT5sV9wYbLmQe3hGdR6uAoPiK4zCxN2", "error": null, "publishedAt": "2027-03-15T09:00:04.000Z", "metrics": { "impressions": 1234, "reach": 987, "likes": 123, "comments": 12, "shares": 4, "saves": null, "views": 456, "engagement": 139 }, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-16T09:00:00.000Z" } ``` | Status | What happens | | --- | --- | | `scheduled` | The post is cancelled and becomes `cancelled` | | `publishing` | The post is cancelled if it has not reached the platform yet. Otherwise you get `409 POST_PUBLISHING`. Try again once its status is final | | `published` | The post is deleted from the platform and becomes `deleted`. A thread is deleted with all its replies | | `failed` | If part of the post went live, such as the first posts of a thread, that part is deleted. Otherwise you get `409 NOT_DELETABLE` | | `cancelled`, `deleted` | Nothing changes | - The delete happens during the request. A `200` with `status: "deleted"` means the platform removed the post, and the `post.deleted` webhook fires. - The post keeps its record in Onepostly with its final status. - Other posts of the same group are not affected. - Posts made outside Onepostly return `409 NOT_DELETABLE`. Delete them on the platform. - On X, each delete is paid from the wallet, once for each post of a thread. See [X Wallet](/docs/pricing#x-wallet). ### Platform Support [#platform-support] Every platform can delete published posts except TikTok, which returns `400 UNSUPPORTED_PLATFORM`. Instagram can only delete posts of accounts connected with Facebook Login. Accounts connected with Instagram Login return `400 MEDIA_DELETE_UNSUPPORTED`. Every platform is compared in [Capabilities](/docs/platforms#capabilities). ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `UNSUPPORTED_PLATFORM` | 400 | The platform cannot delete posts through the API, such as TikTok | Delete the post on the platform | | `MEDIA_DELETE_UNSUPPORTED` | 400 | The Instagram account is connected with Instagram Login | Reconnect with Facebook Login, or delete the post in Instagram | | `INSUFFICIENT_WALLET` | 402 | The wallet does not cover deleting an X post | Top up the wallet, then try again | | `NOT_DELETABLE` | 409 | Nothing of the post is live, or it was made outside Onepostly | Only delete posts that are live | | `POST_PUBLISHING` | 409 | The post is being published right now | Try again once its status is final | | `TOKEN_INVALID`, `TOKEN_EXPIRED` | 409 | The account's access was revoked or expired | [Reconnect the account](/docs/account-status#reconnect-an-account), then try again | | `DELETE_PERMISSION`, `PERMISSION_DENIED` | 422 | The account cannot delete this post, or the platform refused | Reconnect and approve every permission, and check that the account owns the post | | `QUOTA_EXCEEDED` | 429 | The platform is at capacity for deletes | Try again after the time in the message | | `THREAD_DELETE_PARTIAL` | 502 | The first post was deleted, but some posts of its thread were not | Send the delete again | | `DELETE_FAILED`, `PLATFORM_UNAVAILABLE` | 502 | The platform did not delete the post, or did not respond | Try again later, and check the post on the platform | Every other code is in [Errors](/docs/error-handling#error-codes). # Create Posts (/docs/publishing) One request publishes to up to 50 accounts. Each gets its own post, with its own id and status. ## Create a Post [#create-a-post] **TypeScript** ```typescript 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": "New release notes are up.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" }, { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "New release notes are up.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" }, { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "New release notes are up.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" }, { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "New release notes are up.", "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" }, { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "platform": "bluesky", "source": "onepostly", "status": "publishing", "text": "New release notes are up.", "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" } ] } ``` | Field | Type | Description | | --------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `text` | `string` | The post text for every account that does not set its own. Can be empty when the post has media. Default `""`. | | `mediaKind` | `string` | The kind of post. See [Media Kinds](#media-kinds). You only need it for a Facebook `reel` and for `stories`. | | `media` | `MediaRef[]` | Up to 35 files, in order. Send `{ "id": "med_..." }` for a file you uploaded with [Media](/docs/media-uploads), or `{ "url": "https://..." }` for a public HTTPS URL. Each platform's own maximum applies. Default `[]`. | | `accounts` (required) | `AccountTarget[]` | 1 to 50 accounts to publish to. Each takes an `accountId` and optional [per-account settings](#per-account-settings). | | `scheduledFor` | `string` | When to publish, as a local date and time such as `2027-03-15T09:00:00`. Leave it out to publish now. See [Scheduling and Editing](/docs/scheduling). | | `timezone` | `string` | The IANA time zone of `scheduledFor`, such as `America/New_York`. Default `UTC`. Only allowed together with `scheduledFor`. | | `thread` | `ThreadItem[]` | 1 to 25 posts published as replies under the first one, in order. X, Threads and Bluesky only. See [Threads, Replies and Quotes](/docs/replies-and-quotes). | The `201` response has the request's `groupId` and one post per account in `data`, in `accounts` order. - Each post starts as `publishing`, or `scheduled` with `scheduledFor`. Follow it with [Post Status](/docs/post-lifecycle#post-status) or the [post webhooks](/docs/webhooks/posts). - The request is all or nothing. If any account cannot take the post, nothing is created. See [Cross-Posting Rules](#cross-posting-rules). - After the `201`, each post publishes on its own, so one can fail while another is published. - To retry safely after a timeout, send an [Idempotency-Key](/docs/idempotency). ## Media Kinds [#media-kinds] `mediaKind` sets the kind of post. You can usually leave it out. | Request | Default `mediaKind` | | --- | --- | | No `media` | `text` | | 2 or more files | `multi_image` | | 1 file | `video`, `document` or `image`, by file extension | Set `reel` or `stories` yourself, since those files look like a normal video or image. On Instagram, one video always publishes as a Reel and reads `mediaKind: "reel"`. | `mediaKind` | Publishes | `media` | Platforms | | ------------- | ------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------ | | `text` | A text-only post | None | X, Facebook, Threads, LinkedIn, Bluesky | | `image` | One image | Exactly 1 | X, Instagram, Facebook, Threads, LinkedIn, TikTok, Pinterest, Bluesky | | `multi_image` | A carousel or image set | 2 or more, up to the platform maximum | X, Instagram, Facebook, Threads, LinkedIn, TikTok, Bluesky | | `video` | One video. On Instagram, a Reel | Exactly 1 | X, Instagram, Facebook, Threads, LinkedIn, YouTube, TikTok, Pinterest, Bluesky | | `reel` | A Reel | Exactly 1 | Instagram, Facebook | | `document` | A document post | Exactly 1 | LinkedIn | | `stories` | A story | Exactly 1 | Instagram, Facebook | A file count that does not match the kind returns `400 VALIDATION_ERROR`. Each platform's maximum is in [Post Types](/docs/platforms#post-types). ## Per-Account Settings [#per-account-settings] Each entry in `accounts` can carry settings for that account only. | Field | Effect | | --- | --- | | `text` | Replaces the shared `text` for this account | | `` | Options for this account's platform, under the platform's id, such as `tiktok` or `pinterest` | **TypeScript** ```typescript 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": "Behind the scenes at the studio.", "media": [ { "url": "https://cdn.onepostly.com/media/studio-tour.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "firstComment": "Full tour on our site." } }, { "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "text": "Studio tour #behindthescenes", "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Behind the scenes at the studio.", "media": [ { "url": "https://cdn.onepostly.com/media/studio-tour.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "firstComment": "Full tour on our site." } }, { "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "text": "Studio tour #behindthescenes", "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Behind the scenes at the studio.", "media": [ { "url": "https://cdn.onepostly.com/media/studio-tour.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "firstComment": "Full tour on our site." } }, { "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "text": "Studio tour #behindthescenes", "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "publishing", "text": "Behind the scenes at the studio.", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/studio-tour.mp4" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "instagram": { "firstComment": "Full tour on our site." } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" }, { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "platform": "tiktok", "source": "onepostly", "status": "publishing", "text": "Studio tour #behindthescenes", "mediaKind": "video", "media": [ { "url": "https://cdn.onepostly.com/media/studio-tour.mp4" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` Options are optional, except the TikTok and Pinterest ones in [Options by Platform](#options-by-platform). A wrong option returns `400 VALIDATION_ERROR` with the field in `param`. | Request | `param` | | --- | --- | | Options for another platform | `accounts.0.tiktok` | | An option the platform does not have | `accounts.0.tiktok.unknownOption` | | An option for another `mediaKind` | `accounts.0.instagram.shareToFeed` | | A missing required option | `accounts.0.tiktok.allowDuet` | Each post returns its options in `options`, under its own platform's id, or `{}` when it has none. Ignore keys you do not know. To change options later, see [Edit a Scheduled Post](/docs/scheduling#edit-a-scheduled-post). ### Options by Platform [#options-by-platform] Every option, with its type, values and rules, is on the platform's page. | Platform | Key | Required options | | --- | --- | --- | | [X (Twitter)](/docs/x#options) | `x` | None | | [Instagram](/docs/instagram#options) | `instagram` | None | | [Facebook](/docs/facebook#options) | `facebook` | None | | [Threads](/docs/threads#options) | `threads` | None | | [LinkedIn](/docs/linkedin#options) | `linkedin` | None | | [YouTube](/docs/youtube#options) | `youtube` | None | | [TikTok](/docs/tiktok#options) | `tiktok` | `privacyLevel`, `allowComment`. Videos also `allowDuet` and `allowStitch` | | [Pinterest](/docs/pinterest#options) | `pinterest` | `boardId` | | [Bluesky](/docs/bluesky#options) | `bluesky` | None | ### Shared and Per-Account Text [#shared-and-per-account-text] | Text | Has to fit | | --- | --- | | Shared `text` | Every account that uses it. Give an account its own `text` when it is too long there | | Per-account `text` | Its own account only | | `thread[].text` | Every account. Threads cannot be set per account | | Options such as `title` | The account's own platform | Limits can differ by account, such as a longer limit for X Premium. Every limit is in [Text Limits](/docs/platforms#text-limits). ### Example [#example] One image post to X, Instagram, LinkedIn and Pinterest, each with its own settings. **TypeScript** ```typescript 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": "Our spring collection is live.", "media": [ { "url": "https://cdn.onepostly.com/media/spring.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "geoRestriction": [ "US", "CA" ] } }, { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "firstComment": "Shop the collection at the link in our bio.", "userTags": [ { "username": "studio.north", "x": 0.5, "y": 0.5 } ] } }, { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "linkedin": { "firstComment": "Read the design notes on our blog." } }, { "accountId": "acc_YOUR_PINTEREST_ACCOUNT_ID", "pinterest": { "boardId": "1234567890123456789", "title": "Spring Collection", "link": "https://example.com/spring" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Our spring collection is live.", "media": [ { "url": "https://cdn.onepostly.com/media/spring.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "geoRestriction": [ "US", "CA" ] } }, { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "firstComment": "Shop the collection at the link in our bio.", "userTags": [ { "username": "studio.north", "x": 0.5, "y": 0.5 } ] } }, { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "linkedin": { "firstComment": "Read the design notes on our blog." } }, { "accountId": "acc_YOUR_PINTEREST_ACCOUNT_ID", "pinterest": { "boardId": "1234567890123456789", "title": "Spring Collection", "link": "https://example.com/spring" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Our spring collection is live.", "media": [ { "url": "https://cdn.onepostly.com/media/spring.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "geoRestriction": [ "US", "CA" ] } }, { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "firstComment": "Shop the collection at the link in our bio.", "userTags": [ { "username": "studio.north", "x": 0.5, "y": 0.5 } ] } }, { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "linkedin": { "firstComment": "Read the design notes on our blog." } }, { "accountId": "acc_YOUR_PINTEREST_ACCOUNT_ID", "pinterest": { "boardId": "1234567890123456789", "title": "Spring Collection", "link": "https://example.com/spring" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "Our spring collection is live.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/spring.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "x": { "geoRestriction": [ "US", "CA" ] } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" }, { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "publishing", "text": "Our spring collection is live.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/spring.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "instagram": { "firstComment": "Shop the collection at the link in our bio.", "userTags": [ { "username": "studio.north", "x": 0.5, "y": 0.5 } ] } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" }, { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a03", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "platform": "linkedin", "source": "onepostly", "status": "publishing", "text": "Our spring collection is live.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/spring.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "linkedin": { "firstComment": "Read the design notes on our blog." } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" }, { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a04", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_PINTEREST_ACCOUNT_ID", "platform": "pinterest", "source": "onepostly", "status": "publishing", "text": "Our spring collection is live.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/spring.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "pinterest": { "boardId": "1234567890123456789", "title": "Spring Collection", "link": "https://example.com/spring" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` ## Cross-Posting Rules [#cross-posting-rules] Every account is checked before anything is created. If one check fails, the request returns an error and no post is created. | Check | Error | | --- | --- | | Every `accountId` is an `acc_` id | `400 VALIDATION_ERROR` | | Every account is in this workspace | `404 ACCOUNT_NOT_FOUND` | | Every account is `active` | `409 CONNECTION_INACTIVE` | | Every `media[].id` is in this workspace | `404 MEDIA_NOT_FOUND` | | The workspace is not [blocked on billing](/docs/pricing#billing-blocks) | `402` | | Every platform supports the [`mediaKind`](#media-kinds) | `400 VALIDATION_ERROR` | | Every text fits its [limits](#shared-and-per-account-text) | `400 VALIDATION_ERROR` | | Every platform supports `thread` and each option sent | `400 VALIDATION_ERROR` | | The [wallet](/docs/pricing#x-wallet) covers every X post | `402 INSUFFICIENT_WALLET` | | No account is over its [publishing limit](/docs/rate-limits#publishing-limits) | `429 RATE_LIMITED` | A scheduled post meets the publishing limit when it publishes. Media is checked as each post publishes, so a rejected file fails only that account's post, with a code in `error`. Check your files against [Media](/docs/media-uploads) and each platform's Media Requirements first, such as [X](/docs/x#media-requirements). ## List Posts [#list-posts] `GET /v1/posts` lists your posts, newest first, including [posts a sync found](#posts-made-outside-onepostly). **TypeScript** ```typescript import { Configuration, PostsApi } from "@onepostly/sdk"; const postsApi = new PostsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await postsApi.listPosts({ limit: 20, status: "scheduled,published", platform: "instagram", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.list_posts( limit=20, status="scheduled,published", platform="instagram", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts?limit=20&status=scheduled%2Cpublished&platform=instagram" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e02", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "scheduled", "text": "Our summer collection drops next week.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/summer.jpg" } ], "thread": [], "scheduledFor": "2027-03-20T09:00:00", "timezone": "America/New_York", "options": {}, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T10:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" }, { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "published", "text": "Our spring collection is live.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/spring.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "17895695668004550", "url": "https://www.instagram.com/p/DHb7x2ySk4N/", "error": null, "publishedAt": "2027-03-15T09:00:04.000Z", "metrics": { "impressions": 1234, "reach": 987, "likes": 123, "comments": 12, "shares": 4, "saves": 2, "views": 1234, "engagement": 141 }, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:04.000Z" } ], "nextCursor": null, "hasMore": false } ``` 50 posts per page by default, up to 100 with `limit`. Pass `nextCursor` as `cursor` until `hasMore` is `false`. | Parameter | Effect | | --- | --- | | `status` | Comma-separated, such as `scheduled,published` | | `platform` | Only posts on this platform | | `accountId` | Only posts of this account | | `profile` | Only posts of this [profile](/docs/profiles), or `none` | | `groupId` | Only the posts of one create request | | `source` | `onepostly`, or `external` for posts made on the platform | | `since`, `until` | A [time window](/docs/pagination#time-filters) on the schedule, publish or creation time | | `sort` | The order. See below | | `include` | `total` for the count, `facets` for counts per status and platform | | `sort` | Order | | --- | --- | | `created_desc` | Newest first. The default | | `created_asc` | Oldest first | | `published_desc`, `published_asc` | By publish time, unpublished last | | `scheduled_desc`, `scheduled_asc` | By schedule, unscheduled last | | `metric:` | Highest lifetime [metric](/docs/analytics), such as `metric:likes`. Only posts with metrics | Each facet ignores its own filter, so the status counts stay complete while one status is selected. ### Posts Made Outside Onepostly [#posts-made-outside-onepostly] Posts published directly on the platform show up after a sync with `source: "external"`. - `groupId` and `text` are `null`, `media` is `[]` and `options` is `{}`. - The status is `published`, or `deleted` once the post is gone. - [Analytics](/docs/analytics), [comments](/docs/comments) and [engagement](/docs/engagement) work as usual. - Editing returns `409 NOT_EDITABLE`, and deleting `409 NOT_DELETABLE`. Facebook Page posts show up on their own within about a minute and send [`post.created`](/docs/webhooks/posts#posts-made-outside-onepostly). Other platforms need `POST /v1/accounts/{id}/sync`. | Body | Effect | | --- | --- | | None | Syncs the 20 most recent posts | | `url` | Finds the post with this link among them | | `platformPostId` | Finds the post with this platform id among them | **TypeScript** ```typescript import { Configuration, PostsApi } from "@onepostly/sdk"; const postsApi = new PostsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await postsApi.syncAccountPosts({ id: "acc_YOUR_THREADS_ACCOUNT_ID", syncAccountPostsBody: { "url": "https://www.threads.com/@yourbrand/post/DbNQAb8ABC1" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.sync_account_posts( "acc_YOUR_THREADS_ACCOUNT_ID", sync_account_posts_body={ "url": "https://www.threads.com/@yourbrand/post/DbNQAb8ABC1" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts/acc_YOUR_THREADS_ACCOUNT_ID/sync" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://www.threads.com/@yourbrand/post/DbNQAb8ABC1" }' ``` **Response** ```json { "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": null, "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "source": "external", "status": "published", "text": null, "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "18047285913046723", "url": "https://www.threads.com/@yourbrand/post/DbNQAb8ABC1", "error": null, "publishedAt": "2027-03-14T18:30:00.000Z", "metrics": null, "createdAt": "2027-03-15T10:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } ], "skipped": false } ``` `data` is empty when nothing matches. A sync within 15 seconds of the last one returns `skipped: true` with known posts only. Sending both `url` and `platformPostId` returns `400 VALIDATION_ERROR`, and LinkedIn and Pinterest return `400 UNSUPPORTED_PLATFORM`. ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `VALIDATION_ERROR` | 400 | A field breaks a rule. See [Cross-Posting Rules](#cross-posting-rules) | Fix the field in `param` | | `UNSUPPORTED_PLATFORM` | 400 | A sync on LinkedIn or Pinterest | Sync other platforms only | | `PAYMENT_METHOD_REQUIRED`, `PAYMENT_PAST_DUE` | 402 | A [billing block](/docs/pricing#billing-blocks) | Fix billing in the dashboard | | `INSUFFICIENT_WALLET` | 402 | The wallet cannot pay for the X posts | Top up, then retry | | `ACCOUNT_NOT_FOUND` | 404 | An `accountId` is not in this workspace | Use a current id | | `MEDIA_NOT_FOUND` | 404 | A `media[].id` is not in this workspace | Use an id from [Media](/docs/media-uploads) | | `CONNECTION_INACTIVE` | 409 | An account is not `active` | [Reconnect it](/docs/account-status#reconnect-an-account) | | `RATE_LIMITED` | 429 | A [publishing or request limit](/docs/rate-limits) | Wait for `Retry-After` | Errors while a post publishes show up in its `error`, not as HTTP errors. See [Failed Posts](/docs/post-lifecycle#failed-posts) and [Errors](/docs/error-handling#error-codes). # Threads, Replies and Quotes (/docs/replies-and-quotes) Publish a post with a chain of replies under it, publish a post as a reply to another post, or quote a post. These work on X, Threads and Bluesky. | Platform | `thread` | `replyToPostId` | `quotePostId` | | --- | --- | --- | --- | | [X (Twitter)](/docs/x#publish) | Yes | No. Use [Comments](/docs/comments) | Yes | | [Threads](/docs/threads#publish) | Yes | Yes | Yes | | [Bluesky](/docs/bluesky#publish) | Yes | Yes | Yes | | Field | Where | Effect | | --- | --- | --- | | `thread` | Request body | Publishes each item as a reply under the first post, in order | | `replyToPostId` | Platform options, `threads` or `bluesky` | Publishes the post as a reply to an existing post | | `quotePostId` | Platform options, `x`, `threads` or `bluesky` | Quotes an existing post | ## Publish a Thread [#publish-a-thread] Add `thread` to a [Create Post](/docs/publishing) request. The top-level `text`, `mediaKind` and `media` make up the first post, and each `thread` item is one reply under it. **TypeScript** ```typescript 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": "Three things we shipped this month.", "thread": [ { "text": "1. Scheduling in any IANA time zone." }, { "text": "2. Remote delete for whole threads." }, { "text": "3. Webhooks for posts made outside Onepostly." } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" }, { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Three things we shipped this month.", "thread": [ { "text": "1. Scheduling in any IANA time zone." }, { "text": "2. Remote delete for whole threads." }, { "text": "3. Webhooks for posts made outside Onepostly." } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" }, { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Three things we shipped this month.", "thread": [ { "text": "1. Scheduling in any IANA time zone." }, { "text": "2. Remote delete for whole threads." }, { "text": "3. Webhooks for posts made outside Onepostly." } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" }, { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "Three things we shipped this month.", "mediaKind": "text", "media": [], "thread": [ { "text": "1. Scheduling in any IANA time zone.", "media": [] }, { "text": "2. Remote delete for whole threads.", "media": [] }, { "text": "3. Webhooks for posts made outside Onepostly.", "media": [] } ], "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" }, { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "source": "onepostly", "status": "publishing", "text": "Three things we shipped this month.", "mediaKind": "text", "media": [], "thread": [ { "text": "1. Scheduling in any IANA time zone.", "media": [] }, { "text": "2. Remote delete for whole threads.", "media": [] }, { "text": "3. Webhooks for posts made outside Onepostly.", "media": [] } ], "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" } ] } ``` | Rule | Detail | | --- | --- | | Length | 1 to 25 items | | Each item | `text` and up to 20 `media` files, given as `id` or `url` like the post's own `media`. An item needs text or media | | First post | Needs `text` or `media` | | Text limits | Each item's `text` has to fit every account of the request | | Per account | Thread items cannot be set per account. Every account publishes the same replies | | Platforms | Every account of the request has to be on X, Threads or Bluesky. Otherwise the request returns `400 VALIDATION_ERROR` | Each platform limits the media of one reply, such as 4 images on X. The limits are in each platform's Media Requirements section. The post returns its replies in `thread`, and has one `id` for the whole thread. - On X, each post of the thread is charged from the wallet. See [X Wallet](/docs/pricing#x-wallet). - Deleting the post deletes every post of the thread. See [Delete a Post](/docs/post-lifecycle#delete-a-post). - If a reply fails after earlier posts went live, the post ends as `failed`. See [Threads That Fail Partway](/docs/post-lifecycle#threads-that-fail-partway). - To change the thread of a scheduled post, send the whole new `thread` with [Edit a Scheduled Post](/docs/scheduling#edit-a-scheduled-post). ## Reply to a Post [#reply-to-a-post] Set `replyToPostId` in the account's `threads` or `bluesky` options. The post publishes as a reply to that post. **TypeScript** ```typescript 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": "Here is how we set this up.", "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "threads": { "replyToPostId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Here is how we set this up.", "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "threads": { "replyToPostId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Here is how we set this up.", "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "threads": { "replyToPostId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e02", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e02", "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "source": "onepostly", "status": "publishing", "text": "Here is how we set this up.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": { "threads": { "replyToPostId": "18047285913046723" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` On X, a reply to a post is a comment. Use [Comment on a Post](/docs/comments#comment-on-a-post) instead. ## Quote a Post [#quote-a-post] Set `quotePostId` in the account's `x`, `threads` or `bluesky` options. The post publishes with the quoted post embedded. **TypeScript** ```typescript 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": "Worth reading if you run scheduled jobs.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "quotePostId": "1960956321831854280" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Worth reading if you run scheduled jobs.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "quotePostId": "1960956321831854280" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Worth reading if you run scheduled jobs.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "quotePostId": "1960956321831854280" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "Worth reading if you run scheduled jobs.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": { "x": { "quotePostId": "1960956321831854280" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` ## Post References [#post-references] `replyToPostId` and `quotePostId` name the post in one of two ways. | Value | Example | Rule | | --- | --- | --- | | A `pst_` id | `pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73` | A post of this workspace that is live on the same platform. Posts made outside Onepostly work too, once a [sync](/docs/publishing#posts-made-outside-onepostly) found them | | The platform's own id | `1960956321831854280` | The numeric post id on X and Threads, or the `at://` URI on Bluesky. Use it for posts of other accounts. The platform decides whether the account can reply to or quote the post | - A `pst_` id of a post on another platform returns `400 VALIDATION_ERROR`. - A `pst_` id of a post that is not live, such as a `scheduled` or `failed` post, returns `409 POST_NOT_PUBLISHED`. Wait for `post.published`, or use the platform's own id. - A platform id is sent to the platform as it is. If the platform cannot find the post, the post fails when it publishes, with the code in `error`. ## Platform Differences [#platform-differences] Media per reply, text limits and the codes each platform returns are on its page. - [X](/docs/x#publish). Replies to existing posts go through [Comments](/docs/comments). - [Threads](/docs/threads#publish). - [Bluesky](/docs/bluesky#publish). A Bluesky reference has to be an `at://` URI or a `pst_` id. ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `VALIDATION_ERROR` | 400 | A thread item is empty, an account's platform has no threads, or a `pst_` reference is on another platform | Fix the field named in `param` or `error` | | `INSUFFICIENT_WALLET` | 402 | The wallet does not cover every post of an X thread | Top up the wallet. See [X Wallet](/docs/pricing#x-wallet) | | `POST_NOT_PUBLISHED` | 409 | `quotePostId` or `replyToPostId` names a `pst_` post that is not live | Wait for `post.published`, or use the platform's own post id | | `INVALID_QUOTE`, `INVALID_REPLY` | Post error | The Bluesky post to quote or reply to is not a valid `at://` URI, or could not be found | Use the `pst_` id or `at://` URI of an existing post | Every other code is in [Errors](/docs/error-handling#error-codes). # Scheduling and Editing (/docs/scheduling) Set a local date and time and a time zone, and the post publishes then. While it waits, you can change it or cancel it. ## Schedule a Post [#schedule-a-post] Add `scheduledFor` and `timezone` to a [Create Post](/docs/publishing) request. **TypeScript** ```typescript 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": "Join our product webinar next week.", "scheduledFor": "2027-03-15T09:00:00", "timezone": "America/New_York", "accounts": [ { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Join our product webinar next week.", "scheduledFor": "2027-03-15T09:00:00", "timezone": "America/New_York", "accounts": [ { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Join our product webinar next week.", "scheduledFor": "2027-03-15T09:00:00", "timezone": "America/New_York", "accounts": [ { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e02", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e02", "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "platform": "linkedin", "source": "onepostly", "status": "scheduled", "text": "Join our product webinar next week.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": "2027-03-15T09:00:00", "timezone": "America/New_York", "options": {}, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-08T15:00:00.000Z", "updatedAt": "2027-03-08T15:00:00.000Z" } ] } ``` Each post is created with the status `scheduled`, and the [`post.scheduled`](/docs/webhooks/posts) webhook fires. The post returns the schedule as you sent it, with seconds added. | Rule | Detail | | --- | --- | | `scheduledFor` format | A local date and time, `YYYY-MM-DDTHH:MM`, with optional seconds and milliseconds. No `Z` and no offset such as `-05:00`. Those return `400 VALIDATION_ERROR` | | `timezone` | An IANA time zone, such as `America/New_York` or `Europe/Berlin`. Without it, the time is in UTC. `timezone` without `scheduledFor` returns `400 VALIDATION_ERROR` | | Daylight saving | The time is read with the zone's rules on that date. `09:00` in `America/New_York` is 9 AM local time in winter and in summer | | Furthest ahead | 1 year | | Less than 1 minute ahead | Publishes right away. The post starts as `publishing` | | In the past | Up to 5 minutes in the past publishes right away. Further in the past returns `400 VALIDATION_ERROR` | | Invalid dates | A date that does not exist, such as `2027-02-30T09:00:00`, returns `400 VALIDATION_ERROR` | ### When It Publishes [#when-it-publishes] The request is checked against every [cross-posting rule](/docs/publishing#cross-posting-rules) when you schedule it, except the publishing limits. A few things are checked again when the post is due. | At the scheduled time | Outcome | | --- | --- | | The account is over its [publishing limit](/docs/rate-limits#publishing-limits) | The post fails with `RATE_LIMITED` | | The account was disconnected, or its access was revoked | The post fails with `CONNECTION_INACTIVE` | | The wallet no longer covers an X post. X posts are charged when they publish, not when you schedule them | The post fails with `INSUFFICIENT_WALLET` | | The workspace is blocked on billing | The post stays `scheduled` and publishes once billing is fixed. See [Billing Blocks](/docs/pricing#billing-blocks) | Uploaded files that a scheduled post uses are kept until it publishes, even past their usual 7-day expiry. See [Expiry](/docs/media-uploads#expiry). ## Edit a Scheduled Post [#edit-a-scheduled-post] `PATCH /v1/posts/{id}` changes a post while it is `scheduled`. Only the fields you send change, and the result is checked again like a new post. **TypeScript** ```typescript import { Configuration, PostsApi } from "@onepostly/sdk"; const postsApi = new PostsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await postsApi.updatePost({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", updatePostBody: { "scheduledFor": "2027-03-16T09:00:00", "options": { "instagram": { "firstComment": "Register at the link in our profile." } } }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.update_post( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", update_post_body={ "scheduledFor": "2027-03-16T09:00:00", "options": { "instagram": { "firstComment": "Register at the link in our profile." } } }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X PATCH "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "scheduledFor": "2027-03-16T09:00:00", "options": { "instagram": { "firstComment": "Register at the link in our profile." } } }' ``` **Response** ```json { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "scheduled", "text": "Join our product webinar next week.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": "2027-03-16T09:00:00", "timezone": "America/New_York", "options": { "instagram": { "firstComment": "Register at the link in our profile." } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } ``` | Field | Effect | | --- | --- | | `text` | Replaces the post's text | | `media` | Replaces the files. Without `mediaKind`, the kind is worked out again from the new files | | `mediaKind` | Changes the kind. Leave it out to keep the current one | | `thread` | Replaces the whole thread. An empty list removes it | | `scheduledFor` | Moves the post. It has to be at least 1 minute ahead. Leave it out to keep the current time | | `timezone` | Changes the time zone. Without it, a new `scheduledFor` keeps the post's time zone | | `options` | Changes options under the post's platform id, as in Create Post. Only the options you send change, and `null` removes one | - An edit applies to this post only. If the post shares its group with posts on other accounts, it gets a new `groupId` and the other posts keep theirs. - `options` for another platform returns `400 VALIDATION_ERROR` with the key in `param`, such as `options.tiktok`. - An edit to the `text` or `thread` of an X post returns `402 INSUFFICIENT_WALLET` when the wallet does not cover the edited post. - You cannot change the account. Cancel the post and create a new one. - A post that is no longer `scheduled`, or that was made outside Onepostly, returns `409 NOT_EDITABLE`. - To publish a scheduled post now, cancel it and create it again without `scheduledFor`. The response is the updated post, and the [`post.updated`](/docs/webhooks/posts#postupdated) webhook fires. ## Cancel a Scheduled Post [#cancel-a-scheduled-post] `DELETE /v1/posts/{id}` cancels a post that has not been published yet. The post keeps its record with the status `cancelled`, and the `post.cancelled` webhook fires. **TypeScript** ```typescript import { Configuration, PostsApi } from "@onepostly/sdk"; const postsApi = new PostsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await postsApi.deletePost({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.delete_post( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X DELETE "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "cancelled", "text": "Join our product webinar next week.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": "2027-03-16T09:00:00", "timezone": "America/New_York", "options": { "instagram": { "firstComment": "Register at the link in our profile." } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T11:00:00.000Z" } ``` | Status | What happens | | --- | --- | | `scheduled` | The post becomes `cancelled` | | `publishing` | The post becomes `cancelled` if it has not reached the platform yet. Otherwise you get `409 POST_PUBLISHING`. Try again once its status is final | | `cancelled` | Nothing changes | Cancelling one post does not affect the other posts of its group. A cancelled post cannot be scheduled again, so create a new post instead. To remove a post that is already live, see [Delete a Post](/docs/post-lifecycle#delete-a-post). ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `VALIDATION_ERROR` | 400 | The schedule is invalid, an edit leaves `scheduledFor` less than 1 minute ahead, or the edited post breaks a [cross-posting rule](/docs/publishing#cross-posting-rules) | Fix the field named in `param` | | `INSUFFICIENT_WALLET` | 402 | The wallet does not cover the X posts you schedule, or an edit to the text or thread of an X post. Nothing is created or changed | Top up the wallet. See [X Wallet](/docs/pricing#x-wallet) | | `ACCOUNT_NOT_FOUND` | 404 | The post's account was disconnected | Create a new post for a connected account | | `CONNECTION_INACTIVE` | 409 | The post's account needs a reconnect | [Reconnect the account](/docs/account-status#reconnect-an-account), then edit again | | `NOT_EDITABLE` | 409 | The post is not `scheduled`, or was made outside Onepostly | Only edit scheduled posts | | `POST_PUBLISHING` | 409 | The post is being published right now, so it cannot be cancelled | Try again once its status is final | Every other code is in [Errors](/docs/error-handling#error-codes). # Analytics (/docs/analytics) Read post metrics such as views and likes, follow them day by day, and read account insights. Every platform uses the same metric fields. Each post also carries its latest metrics in `metrics`. ## Support by Platform [#support-by-platform] | Platform | Post analytics | Daily timeline | Account insights | Account stats | Updated | |---|---|---|---|---|---| | [X (Twitter)](/docs/x#analytics) | Yes | No | No | No | When you ask, paid per read | | [Instagram](/docs/instagram#analytics) | Yes | Yes | Yes | Yes | Hourly, then weekly | | [Facebook](/docs/facebook#analytics) | Yes | Yes | Yes | Yes | Hourly, then weekly | | [Threads](/docs/threads#analytics) | Yes | Yes | No | No | Hourly, then weekly | | [YouTube](/docs/youtube#analytics) | Yes | Yes | No | No | Hourly, then weekly | | [TikTok](/docs/tiktok#analytics) | Yes | Yes | No | Yes | Hourly, then weekly | | [Bluesky](/docs/bluesky#analytics) | Yes | Yes | No | Yes | Hourly, then weekly | | [LinkedIn](/docs/linkedin#analytics) | No | No | No | No | Not available | | [Pinterest](/docs/pinterest#analytics) | No | No | No | No | Not available | LinkedIn and Pinterest post metrics are not available through Onepostly. Their posts are `pending` right after publishing and `unsupported` after the first reading, and that status is final. Each platform page shows how its metrics map to these fields in its Analytics section. ## Read Post Analytics [#read-post-analytics] `GET /v1/posts/{id}/analytics` returns a post's lifetime metrics, with a `status`, `fetchedAt` and `error`. It works for posts made through Onepostly and for posts a [sync](/docs/publishing#posts-made-outside-onepostly) found. **TypeScript** ```typescript import { Configuration, AnalyticsApi } from "@onepostly/sdk"; const analyticsApi = new AnalyticsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await analyticsApi.getPostAnalytics({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.analytics_api import AnalyticsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: analytics_api = AnalyticsApi(api_client) response = await analytics_api.get_post_analytics( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/analytics" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "status": "ready", "metrics": { "impressions": 1456, "reach": 987, "likes": 123, "comments": 12, "shares": 4, "saves": 2, "views": 1456, "engagement": 141 }, "fetchedAt": "2027-03-15T10:00:00.000Z", "error": null } ``` | Field | Contains | |---|---| | `status` | Where the metrics stand. See [Analytics Status](#analytics-status) | | `metrics` | The same 8 metrics on every platform. One the platform does not report is `null` | | `fetchedAt` | When the platform was last read, in UTC. `null` before the first reading, and always `null` on X | | `error` | The `code` and `message` of the last failed reading, or `null` | ## Freshness [#freshness] | Post age | Metrics update | |---|---| | Under 30 days | About every hour | | 30 days or older | About once a week, for as long as the post exists | - Asking more often than this table returns the same reading. Check `fetchedAt` to see how fresh it is. - A new post gets its first reading within about an hour of publishing. - A post made outside Onepostly gets its first reading within about an hour of the [sync](/docs/publishing#posts-made-outside-onepostly) that found it. - Instagram and Facebook Stories update about every hour for their 24 hours live. After that, the last values stay. - Some platforms report reach and impressions hours or days late. Until then, they are `null` or `0`. - Metrics pause while the account needs a [reconnect](/docs/account-status#reconnect-an-account) or [billing](/docs/pricing#billing-blocks) blocks the workspace. ### X Analytics [#x-analytics] X metrics are read when you ask, at most once per post and UTC day. The first request of the day is paid from your [wallet](/docs/pricing#x-wallet), or returns `402 INSUFFICIENT_WALLET` when the balance is too low. Later requests that day are free. X posts have no `fetchedAt` and no daily timeline. ## Daily Timeline [#daily-timeline] `GET /v1/posts/{id}/analytics/timeline` returns a post's metrics with one point per UTC day. Set the range with `since` and `until`, as in [Time Filters](/docs/pagination#time-filters). Each covers its whole UTC day. Without them, you get the last 90 days, which is also the longest range and how far back history goes. **TypeScript** ```typescript import { Configuration, AnalyticsApi } from "@onepostly/sdk"; const analyticsApi = new AnalyticsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await analyticsApi.getPostAnalyticsTimeline({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", since: "2027-03-01T00:00:00Z", until: "2027-03-29T00:00:00Z", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.analytics_api import AnalyticsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: analytics_api = AnalyticsApi(api_client) response = await analytics_api.get_post_analytics_timeline( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", since="2027-03-01T00:00:00Z", until="2027-03-29T00:00:00Z", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/analytics/timeline?since=2027-03-01T00%3A00%3A00Z&until=2027-03-29T00%3A00%3A00Z" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "from": "2027-03-01", "to": "2027-03-28", "points": [ { "day": "2027-03-15", "metrics": { "impressions": 310, "reach": 262, "likes": 28, "comments": 3, "shares": 1, "saves": 0, "views": 310, "engagement": 32 }, "delta": { "impressions": null, "reach": null, "likes": null, "comments": null, "shares": null, "saves": null, "views": null, "engagement": null } }, { "day": "2027-03-16", "metrics": { "impressions": 1980, "reach": 1610, "likes": 141, "comments": 13, "shares": 5, "saves": 3, "views": 1980, "engagement": 162 }, "delta": { "impressions": 1670, "reach": 1348, "likes": 113, "comments": 10, "shares": 4, "saves": 3, "views": 1670, "engagement": 130 } }, { "day": "2027-03-17", "metrics": { "impressions": 2650, "reach": 2140, "likes": 182, "comments": 17, "shares": 6, "saves": 4, "views": 2650, "engagement": 209 }, "delta": { "impressions": 670, "reach": 530, "likes": 41, "comments": 4, "shares": 1, "saves": 1, "views": 670, "engagement": 47 } }, { "day": "2027-03-18", "metrics": { "impressions": 3040, "reach": 2450, "likes": 207, "comments": 19, "shares": 7, "saves": 5, "views": 3040, "engagement": 238 }, "delta": { "impressions": 390, "reach": 310, "likes": 25, "comments": 2, "shares": 1, "saves": 1, "views": 390, "engagement": 29 } }, { "day": "2027-03-19", "metrics": { "impressions": 3290, "reach": 2650, "likes": 223, "comments": 21, "shares": 8, "saves": 6, "views": 3290, "engagement": 258 }, "delta": { "impressions": 250, "reach": 200, "likes": 16, "comments": 2, "shares": 1, "saves": 1, "views": 250, "engagement": 20 } }, { "day": "2027-03-20", "metrics": { "impressions": 3450, "reach": 2780, "likes": 233, "comments": 22, "shares": 8, "saves": 6, "views": 3450, "engagement": 269 }, "delta": { "impressions": 160, "reach": 130, "likes": 10, "comments": 1, "shares": 0, "saves": 0, "views": 160, "engagement": 11 } }, { "day": "2027-03-21", "metrics": { "impressions": 3570, "reach": 2870, "likes": 240, "comments": 23, "shares": 9, "saves": 7, "views": 3570, "engagement": 279 }, "delta": { "impressions": 120, "reach": 90, "likes": 7, "comments": 1, "shares": 1, "saves": 1, "views": 120, "engagement": 10 } }, { "day": "2027-03-22", "metrics": { "impressions": 3660, "reach": 2940, "likes": 245, "comments": 23, "shares": 9, "saves": 7, "views": 3660, "engagement": 284 }, "delta": { "impressions": 90, "reach": 70, "likes": 5, "comments": 0, "shares": 0, "saves": 0, "views": 90, "engagement": 5 } }, { "day": "2027-03-23", "metrics": { "impressions": 3730, "reach": 2990, "likes": 249, "comments": 24, "shares": 9, "saves": 7, "views": 3730, "engagement": 289 }, "delta": { "impressions": 70, "reach": 50, "likes": 4, "comments": 1, "shares": 0, "saves": 0, "views": 70, "engagement": 5 } }, { "day": "2027-03-24", "metrics": { "impressions": 3780, "reach": 3030, "likes": 252, "comments": 24, "shares": 9, "saves": 8, "views": 3780, "engagement": 293 }, "delta": { "impressions": 50, "reach": 40, "likes": 3, "comments": 0, "shares": 0, "saves": 1, "views": 50, "engagement": 4 } }, { "day": "2027-03-25", "metrics": { "impressions": 3820, "reach": 3060, "likes": 254, "comments": 24, "shares": 10, "saves": 8, "views": 3820, "engagement": 296 }, "delta": { "impressions": 40, "reach": 30, "likes": 2, "comments": 0, "shares": 1, "saves": 0, "views": 40, "engagement": 3 } }, { "day": "2027-03-26", "metrics": { "impressions": 3850, "reach": 3080, "likes": 256, "comments": 25, "shares": 10, "saves": 8, "views": 3850, "engagement": 299 }, "delta": { "impressions": 30, "reach": 20, "likes": 2, "comments": 1, "shares": 0, "saves": 0, "views": 30, "engagement": 3 } }, { "day": "2027-03-27", "metrics": { "impressions": 3870, "reach": 3095, "likes": 257, "comments": 25, "shares": 10, "saves": 8, "views": 3870, "engagement": 300 }, "delta": { "impressions": 20, "reach": 15, "likes": 1, "comments": 0, "shares": 0, "saves": 0, "views": 20, "engagement": 1 } }, { "day": "2027-03-28", "metrics": { "impressions": 3890, "reach": 3105, "likes": 258, "comments": 25, "shares": 10, "saves": 8, "views": 3890, "engagement": 301 }, "delta": { "impressions": 20, "reach": 10, "likes": 1, "comments": 0, "shares": 0, "saves": 0, "views": 20, "engagement": 1 } } ] } ``` The response has the `postId`, the first and last UTC day it covers as `from` and `to`, and `points`. Each point has a `day`, `metrics` and `delta`. | Field | Contains | |---|---| | `metrics` | Lifetime totals from the day's first reading. Today's point can trail the live metrics | | `delta` | The change since the previous point. A metric is `null` in `delta` when either point is missing it | Days without a reading have no point. Posts 30 days or older are read about once a week, so their timeline has about one point per week. X posts return `400 TIMELINE_UNSUPPORTED`. ## Account Insights [#account-insights] `GET /v1/accounts/{id}/analytics` reads account insights live from the platform. It works for Instagram professional accounts and Facebook Pages. **TypeScript** ```typescript import { Configuration, AnalyticsApi } from "@onepostly/sdk"; const analyticsApi = new AnalyticsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await analyticsApi.getAccountAnalytics({ id: "acc_YOUR_INSTAGRAM_ACCOUNT_ID", metrics: "reach,views", period: "day", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.analytics_api import AnalyticsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: analytics_api = AnalyticsApi(api_client) response = await analytics_api.get_account_analytics( "acc_YOUR_INSTAGRAM_ACCOUNT_ID", metrics="reach,views", period="day", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_INSTAGRAM_ACCOUNT_ID/analytics?metrics=reach%2Cviews&period=day" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "metrics": [ { "name": "reach", "period": "day", "values": [ { "value": 3120, "endTime": null } ] }, { "name": "views", "period": "day", "values": [ { "value": 8450, "endTime": null } ] } ], "demographics": {} } ``` | Parameter | Effect | | --- | --- | | `metrics` | Comma-separated, as the platform names them. Defaults are on the [Instagram](/docs/instagram#account-insights) and [Facebook](/docs/facebook#account-insights) pages | | `period` | `day` (default), `week`, `days_28` or `lifetime` | | `since`, `until` | The range, as ISO 8601 date and time. See [Time Filters](/docs/pagination#time-filters) | | `breakdown`, `timeframe` | Instagram demographics, such as `breakdown=country` with `timeframe=this_month` | | `metricType` | Instagram only. `total_value` for one total, `time_series` for daily values. Default is Instagram's own format | Each metric has `values` with a `value` and an `endTime`. Breakdowns are in `demographics`. A metric, period or breakdown the platform cannot read returns `400 VALIDATION_ERROR` with the platform's reason. For follower counts, use `GET /v1/accounts/{id}/stats` on Instagram, Facebook, TikTok and Bluesky. A count the platform does not report is `null`. ## Analytics Status [#analytics-status] Every post analytics response has a `status`. `unsupported` and `unavailable` are final. **ready** Metrics are in. `fetchedAt` says when they were read. On X, `fetchedAt` is `null`, because X is read when you ask. **pending** The post is published but has no reading yet. Metrics show up by themselves, so read again later. For a post made outside Onepostly, they show up once a [sync](/docs/publishing#posts-made-outside-onepostly) has found it. A TikTok post stays `pending` until TikTok makes it publicly viewable. **failed** The last reading failed, and `error.code` and `error.message` say why. For `CONNECTION_INACTIVE`, `TOKEN_EXPIRED` or `TOKEN_INVALID`, [reconnect the account](/docs/account-status#reconnect-an-account) and metrics come back. For other codes, read again later. **unsupported** The platform does not report metrics for this kind of post, as on LinkedIn and Pinterest. Final. **unavailable** The post can never be measured. It was not published, and `error.code` is `NOT_PUBLISHED`. Or it was deleted on the platform, and `error.code` is `POST_NOT_FOUND`. Or the platform never reports metrics for it, such as a TikTok post published with a privacy level other than `public_to_everyone`. Final. `status` can get new values later, so treat a value you do not know like `pending`. ## Errors [#errors] | Code | HTTP | Cause | Fix | |---|---|---|---| | `NOT_FOUND`, `ACCOUNT_NOT_FOUND` | 404 | The post or account is not in this workspace | Check the id | | `INVALID_RANGE` | 400 | `since` is not before `until`, or the range is over 90 days | Send a range of up to 90 days | | `TIMELINE_UNSUPPORTED` | 400 | The post is on X | Read post analytics instead | | `UNSUPPORTED_PLATFORM` | 400 | Account insights outside Instagram and Facebook | Read post analytics instead | | `INSUFFICIENT_WALLET` | 402 | The wallet cannot pay for an X read | Top up, then read again | | `TOKEN_EXPIRED`, `TOKEN_INVALID` | 409 | The account's access ended | [Reconnect the account](/docs/account-status#reconnect-an-account) | | `ANALYTICS_PERMISSION` | 422 | The account is missing the insights permission | Reconnect and approve every permission | | `ANALYTICS_FAILED` | 502 | The platform did not return account insights | Try again later | Every other code is in [Error Codes](/docs/error-handling#error-codes). # Authentication (/docs/authentication) Every request to `https://api.onepostly.com` needs an API key from your workspace. A key only works for its own workspace. It reaches every account and post in it, or only those of [some profiles](#profile-access). ## Create an API Key [#create-an-api-key] Open **API Keys** in the dashboard. Only the workspace owner can create and delete keys. Click **Create Key** and give the key a name. Pick its permission, expiration, profile access and the parts of the API it can use. Copy the key. It starts with `op_` and is shown only once. None of these choices can be changed later. To change one, create a new key and delete the old one. | Permission | Access | | --- | --- | | `read_write` | Read and write. This is the default | | `read_only` | Read only. Write requests return `403 FORBIDDEN` | ## Expiration [#expiration] A key never expires by default. You can give it a lifetime of 7, 30 or 90 days, or 1 year. After that, every request with it returns `401 UNAUTHORIZED`. The **API Keys** page shows when each key expires. ## Profile Access [#profile-access] A key reaches every [profile](/docs/profiles) by default. You can limit it to some profiles instead, such as a key for each client. | Request | With a key limited to some profiles | | --- | --- | | Accounts, posts, comments, inbox, analytics and automations | Only those of the profiles' accounts. Others return `404` | | Connecting an account | It goes to one of the key's profiles. See below | | `GET /v1/profiles` | Lists only the key's profiles | | Creating, renaming or deleting a profile | `403 FORBIDDEN` | | Media, webhooks and the wallet | The whole workspace, as with any key | When a key with one profile connects an account, the account goes to that profile. A key with several profiles must name one of them in `profile`. Without it, the request returns `400 VALIDATION_ERROR`, and another profile returns `403 FORBIDDEN`. The key keeps working when you rename its profiles. You cannot delete a profile while a key is limited to it. ## Restrict Access [#restrict-access] A key can use the whole API by default. You can turn off parts of it, so the key can only do the work it is made for. A request to a part that is off returns `403 GROUP_DISABLED`, with the part's name in `details.group`. | Part | `details.group` | Endpoints | | --- | --- | --- | | Publishing | `publishing` | `/v1/posts`, `/v1/media` and `POST /v1/accounts/{id}/sync` | | Engagement | `engagement` | Comments, private replies, likes, bookmarks, reposts and reposters | | Messages | `messages` | `/v1/accounts/{id}/conversations` and `/v1/automations` | | Analytics | `analytics` | `/v1/posts/{id}/analytics` and `/v1/accounts/{id}/analytics` | | Accounts | `accounts` | `/v1/accounts`, its settings and resources, `/v1/connect-sessions` and `/v1/profiles` | | Billing | `billing` | `/v1/wallet` | | Webhooks | `webhooks` | `/v1/webhooks` and its deliveries | At least one part stays on. ## Send the Key [#send-the-key] Send the key as a bearer token in the `Authorization` header. ```http Authorization: Bearer op_YOUR_KEY ``` ## Use the SDK [#use-the-sdk] The samples in these docs read the key from the `ONEPOSTLY_API_KEY` environment variable. ```bash export ONEPOSTLY_API_KEY="op_YOUR_KEY" ``` This request lists your accounts, so it is a quick way to check that your key works. **TypeScript** ```typescript 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); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.list_accounts() print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "acc_1699f4157fb643f49d2ac447491f3202", "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:05:00.000Z", "updatedAt": "2027-03-01T10:05:00.000Z" }, { "id": "acc_1699f4157fb643f49d2ac447491f32a8", "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-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z" } ], "nextCursor": null, "hasMore": false } ``` See [SDKs](/docs/sdks) to install and configure the Node.js and Python clients. ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `UNAUTHORIZED` | 401 | The key is missing, wrong, expired or deleted | Send the full key and check that it still exists on the **API Keys** page | | `FORBIDDEN` | 403 | A `read_only` key called a write endpoint, or a key limited to some profiles went outside them | Use a key with the access you need | | `GROUP_DISABLED` | 403 | The key's part of the API in `details.group` is off | Use a key that has this part | In TypeScript these errors throw a `ResponseError`, and in Python they raise an `ApiException`. The response body has a `requestId`. Share it with support when you need help. See [Errors](/docs/error-handling#error-envelope). ## Keep Keys Safe [#keep-keys-safe] - Keep keys on your server. Never put them in browser or mobile code, or in version control. - Store them in environment variables or a secret manager. - Use a separate key for each app or environment. Then you can delete one without breaking the others. - Use a `read_only` key for integrations that only read data. - Limit a key to the profiles and parts of the API it needs. - Give a key an expiration when it is only needed for a while. ### Rotate a Key [#rotate-a-key] Create a new key and deploy it. Then delete the old key on the **API Keys** page. Requests that still use the old key return `401 UNAUTHORIZED`. # Changelog (/docs/changelog) ## October 20, 2026 [#october-20-2026] - **Account metadata.** Store your own key-value pairs on an account, such as your user's id. See [Link Accounts to Your Users](/docs/connection#link-accounts-to-your-users). - **Profile access for API keys.** Limit a key to the profiles it works with. See [Profile Access](/docs/authentication#profile-access). - **Restricted API keys.** Turn off the parts of the API a key does not need. See [Restrict Access](/docs/authentication#restrict-access). - **Key expiration.** Give a key a lifetime of 7, 30 or 90 days, or 1 year. See [Expiration](/docs/authentication#expiration). # Glossary (/docs/glossary) A linked term opens the page that explains it. The **Where you meet it** column names the field, id prefix or endpoint that carries the term. ## Workspace and Accounts [#workspace-and-accounts] | Term | Meaning | Where you meet it | | --- | --- | --- | | [Workspace](/docs#how-it-works) | Your organization in Onepostly. It owns the accounts, keys, webhooks and billing | `organizationId` in webhook events | | [API key](/docs/authentication) | The secret your server sends with every request. It belongs to one workspace | `Authorization: Bearer op_...` | | [Permission](/docs/authentication) | What an API key may do, `read_write` or `read_only` | `403 FORBIDDEN` on a `read_only` write | | [Account](/docs/connection) | One connected social account, such as an X account or a Facebook Page | `acc_` ids, `accountId` | | [Profile](/docs/profiles) | A named group of accounts that you connect into and filter by | `profile`, `GET /v1/profiles` | | [Account metadata](/docs/connection#link-accounts-to-your-users) | Your own key-value pairs on an account, such as the id of your user who connected it | `metadata` | | [Default profile](/docs/profiles#the-default-profile) | The profile every workspace starts with. Connects without a `profile` go there | `profile: "Default"` | | [Connect session](/docs/connection#connect-from-your-app) | A short-lived sign-in link that connects an account from your own app | `POST /v1/connect-sessions` | | [Redirect URL](/docs/connection#handle-the-redirect) | The page in your app the browser returns to after a connect or reconnect | `redirectUrl` | | [Headless connect](/docs/connection#pick-a-page-or-account) | A connect session where you show the Page or account picker yourself | `headless: true` | | [Candidate](/docs/connection#pick-a-page-or-account) | A Page or Instagram account the user can pick in a headless connect | `candidateId` | | [Login method](/docs/instagram#connect) | How an Instagram account signs in, directly or through a Facebook Page | `loginMethod` | | [App Password](/docs/connection#connect-bluesky) | A Bluesky password made for one app, used instead of a sign-in screen | `appPassword` | | [Account status](/docs/account-status#status-values) | Whether an account can publish | `status` on an account | | [Auto-renew](/docs/account-status#token-expiry) | Whether an account's access renews without the user signing in again | `canAutoRenew`, `tokenExpiresAt` | | [Reconnect](/docs/account-status#reconnect-an-account) | Renewing the access of an account you have. It keeps its id and profile | `POST /v1/accounts/{id}/reconnect` | | [Disconnect](/docs/account-status#disconnect-an-account) | Removing an account from the workspace | `DELETE /v1/accounts/{id}` | | Account settings | Publishing defaults stored on an account, such as Bluesky post languages | `/v1/accounts/{id}/settings` | | Account stats | Live audience counts, such as followers | `GET /v1/accounts/{id}/stats` | | [X subscription](/docs/x) | The X plan of an X account, which sets its text limit | `xSubscriptionType` | ## Posts and Media [#posts-and-media] | Term | Meaning | Where you meet it | | --- | --- | --- | | [Post](/docs/publishing) | One post on one account, with its own status, link and metrics | `pst_` ids, `GET /v1/posts` | | Group | The posts one create request made, one per account | `groupId`, `grp_` ids | | [Post status](/docs/post-lifecycle#post-status) | Where a post is in its life, such as `scheduled` or `published` | `status` on a post | | [Post error](/docs/error-handling) | Why a post failed | `error.code` on a `failed` post | | Platform post id | The platform's own id for a published post | `platformPostId` | | Post URL | The public link to the post on the platform, once it has one | `url` | | Per-account text | A text for one account instead of the shared `text` | `accounts[].text` | | [Platform options](/docs/platforms) | Settings for one platform, such as a TikTok privacy level | `accounts[].tiktok`, `options` | | Media kind | What a post publishes, such as `multi_image`, `reel` or `stories` | `mediaKind` | | [Media](/docs/media-uploads) | A file you upload for your posts | `med_` ids, `media[].id` | | Media URL | A public HTTPS file URL you pass instead of an upload | `media[].url` | | Upload URL | The address you `PUT` the file to after creating a media item | `uploadUrl` | | [Thread](/docs/replies-and-quotes) | Posts published as replies under the first one, on X, Threads and Bluesky | `thread` | | [Quote](/docs/replies-and-quotes) | A post that embeds another post | `quotePostId` | | [Reply post](/docs/replies-and-quotes) | A post published as a reply to another post, on Threads and Bluesky | `replyToPostId` | | [Scheduled post](/docs/scheduling) | A post that publishes at a set local time | `scheduledFor`, `timezone` | | External post | A post the account published outside Onepostly, found by a sync | `source: "external"` | | [Metrics](/docs/analytics) | A post's lifetime numbers, such as views and likes | `GET /v1/posts/{id}/analytics` | | Analytics status | Whether metrics are ready for a post, such as `ready` or `pending` | `status` in post analytics | | Timeline | A post's metrics day by day | `/v1/posts/{id}/analytics/timeline` | | Account analytics | Account-level insights over a period, with demographic breakdowns | `GET /v1/accounts/{id}/analytics` | ## Engagement and Inbox [#engagement-and-inbox] | Term | Meaning | Where you meet it | | --- | --- | --- | | [Comment](/docs/comments) | A comment or reply on a post | `cmt_` ids, `/v1/posts/{id}/comments` | | Reply | Your answer to a comment | `POST /v1/comments/{id}/replies` | | Hidden comment | A comment hidden from the public on the platform, without deleting it | `/v1/comments/{id}/hidden` | | Private reply | A direct message sent in answer to a public comment | `/v1/comments/{id}/private-reply` | | [Like, repost, bookmark](/docs/engagement) | Engagement your account does on a post | `/v1/accounts/{id}/likes/{postId}` | | Reposters | The accounts that reposted a post | `GET /v1/posts/{id}/reposts` | | [Conversation](/docs/inbox) | A direct message thread between an account and one person | `cnv_` ids | | [Message](/docs/inbox) | One direct message in a conversation | `message.received` | | Messenger profile | The conversation starters and menu a Facebook Page shows in Messenger | `/v1/accounts/{id}/messenger-profile` | | Review | A recommendation left on a Facebook Page | `review.received` | | [Automation](/docs/automations) | A rule that sends a direct message when a comment or message matches keywords | `aut_` ids | ## Webhooks and Events [#webhooks-and-events] | Term | Meaning | Where you meet it | | --- | --- | --- | | [Webhook](/docs/webhooks) | An HTTPS endpoint of yours that receives events | `whk_` ids | | [Event](/docs/webhooks#event-catalog) | Something that happened, such as a published post or a new comment | `type`, `evt_` ids | | Event object | The object the event is about, as it was when the event happened | `data.object` | | Wildcard | A subscription to every event type, including ones added later | `events: ["*"]` | | [Delivery](/docs/webhooks#delivery-and-retries) | One event sent to one webhook, with its attempts | `dlv_` ids | | [Signing secret](/docs/webhooks#verify-signatures) | The secret that signs each delivery, so you can verify it came from Onepostly | `secret` on a new webhook | | Test event | A sample event you send to check your endpoint | `webhook.test` | ## API Basics [#api-basics] | Term | Meaning | Where you meet it | | --- | --- | --- | | Base URL | The address of every API request | `https://api.onepostly.com` | | [Id prefix](/docs/ids) | The start of an id that names its kind, such as `acc_` or `pst_` | Every id | | [Cursor](/docs/pagination) | The position of the next page in a list | `cursor`, `nextCursor`, `hasMore` | | Include | Extras you ask a list to add | `include=total`, `include=facets` | | [Time filters](/docs/pagination#time-filters) | Limits a list to a time window | `since`, `until` | | [Idempotency key](/docs/idempotency) | A unique key that makes a retried request safe | `Idempotency-Key` header | | [Error code](/docs/error-handling) | The stable reason of an error. Build your logic on it | `code` in the error body | | Request id | The id of one request, for support | `Request-Id`, `requestId` | | Open enum | A list of values that can grow, such as `status`. Handle values you do not know | "New values can be added" | | [Rate limit](/docs/rate-limits) | How many requests the workspace can send in a window | `X-RateLimit-*`, `Retry-After` | | [Wallet](/docs/pricing#x-wallet) | The prepaid balance that pays for X actions | `GET /v1/wallet` | | [Billing block](/docs/pricing#billing-blocks) | The state of a workspace that must fix billing before it can use the API | `402 PAYMENT_METHOD_REQUIRED` | | [MCP server](/docs/mcp) | The server that lets AI clients such as Claude use Onepostly as tools | `https://mcp.onepostly.com` | # Introduction (/docs) Onepostly is one API for nine social networks. Write a post once, send it everywhere, and handle the replies and results without learning nine different APIs. ## What Onepostly Does [#what-onepostly-does] | You want to | Use | | --- | --- | | Publish now or later to one or many accounts | [Create Posts](/docs/publishing) and [Scheduling](/docs/scheduling) | | Let your own users connect their accounts | [Connect Accounts](/docs/connection#connect-from-your-app) and [Link Accounts to Your Users](/docs/connection#link-accounts-to-your-users) | | Answer comments and direct messages | [Comments](/docs/comments) and [Inbox](/docs/inbox) | | Read views, likes and follower numbers | [Analytics](/docs/analytics) | | React to events as they happen | [Webhooks](/docs/webhooks) | | Publish from Claude and other AI clients | [MCP Server](/docs/mcp) | Each platform has its own limits and options. Onepostly checks your request against them before publishing, and the [platform pages](/docs/platforms) list every difference. ## How It Works [#how-it-works] | Concept | What it is | Id | | --- | --- | --- | | Workspace | Your organization, with its accounts, API keys and billing | Set by your [API key](/docs/authentication) | | [Profile](/docs/profiles) | A named group of accounts that you connect into and filter by | Its name | | [Account](/docs/connection) | One connected social account, such as a Facebook Page | `acc_` | | Post | One post on one account, with its own status and link | `pst_` | | Group | The posts of one create request, one per account | `grp_` | | [Media](/docs/media-uploads) | An image, video or document you upload, or a public URL | `med_` | | [Webhook](/docs/webhooks) | Your HTTPS endpoint that receives events | `whk_` | Every id starts with a prefix that names its kind. See [Data Formats](/docs/ids). ## The Request Shape [#the-request-shape] One `POST /v1/posts` publishes to every account you list. Shared fields like `text` and `media` apply to all of them, and each `accounts` entry can override the text and add options under its platform's key. **TypeScript** ```typescript 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": "Our spring collection is live.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" }, { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "text": "Our spring collection is live. Made for the first warm days.", "bluesky": { "langs": [ "en" ] } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Our spring collection is live.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" }, { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "text": "Our spring collection is live. Made for the first warm days.", "bluesky": { "langs": [ "en" ] } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Our spring collection is live.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" }, { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "text": "Our spring collection is live. Made for the first warm days.", "bluesky": { "langs": [ "en" ] } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "Our spring collection is live.", "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" }, { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "platform": "bluesky", "source": "onepostly", "status": "publishing", "text": "Our spring collection is live. Made for the first warm days.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": { "bluesky": { "langs": [ "en" ] } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` The response has one post per account, and each succeeds or fails on its own. Every request goes to `https://api.onepostly.com` with your [API key](/docs/authentication). ## What to Read Next [#what-to-read-next] - [Quickstart](/docs/quickstart): Publish your first post in four steps. - [Authentication](/docs/authentication): Create an API key and send it with your requests. - [Create Posts](/docs/publishing): Cross-post, set options per account and list your posts. - [Connect Accounts](/docs/connection): Connect accounts in the dashboard, or let your users connect theirs. - [Compare Platforms](/docs/platforms): What each platform supports and how to connect it. - [Webhooks](/docs/webhooks): Get notified when a post is published or fails. # MCP Server (/docs/mcp) Connect an AI assistant such as Claude, Cursor or Codex to Onepostly and manage your posts from a chat. The assistant talks to Onepostly through the [Model Context Protocol](https://modelcontextprotocol.io/) (MCP). ## What You Can Do [#what-you-can-do] - See your connected accounts and which ones need reconnecting. - Publish now or schedule for later, to one or more accounts at once. Threads on X, Threads and Bluesky work too. - Check whether a post went live, and why it failed if it did. - Read a post's analytics. - Cancel a scheduled post, or delete a published one. - Look up what an account needs before you post, such as a Pinterest board or a TikTok privacy level. Uploading media, connecting accounts, comments, likes, direct messages and webhooks are only in the REST API. To post media from a chat, upload it as described in [Media](/docs/media-uploads) first, then give the assistant the `med_` id or a public URL. See [Tools](/docs/mcp/tools) for every tool and what it takes. ## Server URL [#server-url] ``` https://mcp.onepostly.com ``` `https://mcp.onepostly.com/mcp` also works. The server uses Streamable HTTP and MCP protocol version `2025-11-25`. ## Sign-In [#sign-in] The first time you connect, a browser window opens. Sign in to Onepostly and approve access for your workspace. Your password is never shared, and API keys do not work on the MCP server. You can see and revoke connected apps in **Settings → MCP Connections**. Every tool call counts toward your workspace's [rate limit](/docs/rate-limits), and X posts, deletes and analytics reads are paid from your [wallet](/docs/pricing#x-wallet) as in the REST API. To get started, see [Setup](/docs/mcp/setup). ## Example [#example] **You:** Post "Spring collection is live. Free shipping through Sunday." to X and Bluesky. The assistant calls `accounts_list` to find the account ids. ```json { "accounts": [ { "id": "acc_3f6c2a915d4e4b7a9e1f8a2b6c0d4e57", "platform": "x", "displayName": "Acme", "handle": "acme", "avatarUrl": null, "status": "active" }, { "id": "acc_8b1e7d3c2a9f4c65b0d85e4f1a7c9b23", "platform": "bluesky", "displayName": "Acme", "handle": "acme.bsky.social", "avatarUrl": null, "status": "active" } ] } ``` Then it calls `posts_create` with both accounts. ```json { "text": "Spring collection is live. Free shipping through Sunday.", "accounts": [ { "accountId": "acc_3f6c2a915d4e4b7a9e1f8a2b6c0d4e57" }, { "accountId": "acc_8b1e7d3c2a9f4c65b0d85e4f1a7c9b23" } ] } ``` The tool creates one post per account, both with the status `publishing`. **Assistant:** Your post is on its way to X and Bluesky. **You:** Is it live? The assistant calls `posts_get` for each post. Both are now `published` and have a `url`. **Assistant:** Yes, it is live on both accounts. - X: https://x.com/i/web/status/1899745123456789012 - Bluesky: https://bsky.app/profile/acme.bsky.social/post/3lkq7xz2abc2w # Setup (/docs/mcp/setup) Add Onepostly to Claude, Cursor or any other MCP app. You approve access once in your browser. ## Before You Start [#before-you-start] - A Onepostly workspace with at least one connected account. See [Connect Accounts](/docs/connection). - An app that supports remote MCP servers, such as Claude or Cursor. If yours only runs local servers, use the **Other** tab below. ## Add the Server [#add-the-server] Add `https://mcp.onepostly.com` with the steps for your app below. Start the connection. A browser window opens. Sign in to Onepostly if you are not signed in yet. Check the consent screen. It shows the app, the workspace and the access you are giving. Click **Allow**. To connect another workspace, switch to it in the dashboard first and start again. Ask the assistant to list your accounts. If it does, you are connected. **Claude Code** Add the server. ```bash claude mcp add --transport http onepostly https://mcp.onepostly.com ``` Then run `/mcp` in Claude Code, select **onepostly** and sign in in the browser. **Claude** In Claude, open **Settings → Connectors → Add custom connector** and enter this URL. ``` https://mcp.onepostly.com ``` Click **Connect** on the new connector and approve access in the browser. **Cursor** Add the server to `~/.cursor/mcp.json`, or to `.cursor/mcp.json` in a project. ```json { "mcpServers": { "onepostly": { "url": "https://mcp.onepostly.com" } } } ``` Open **Cursor Settings → MCP** and log in to **onepostly** when asked. See the [Cursor documentation](https://cursor.com/docs/mcp). **VS Code** Add the server to `.vscode/mcp.json` in your workspace. ```json { "servers": { "onepostly": { "type": "http", "url": "https://mcp.onepostly.com" } } } ``` Start the server from the file or with the **MCP: List Servers** command, and approve access in the browser. **Codex** Add the server and sign in. ```bash codex mcp add onepostly --url https://mcp.onepostly.com codex mcp login onepostly ``` The CLI, the desktop app and the IDE extension share this configuration. **MCP Inspector** Start the inspector. ```bash npx @modelcontextprotocol/inspector@latest ``` Select the **Streamable HTTP** transport, enter `https://mcp.onepostly.com`, click **Connect** and approve access in the browser tab that opens. **Other** Any MCP app with OAuth and Streamable HTTP support can connect to `https://mcp.onepostly.com`. If yours only runs local servers, bridge it with [`mcp-remote`](https://www.npmjs.com/package/mcp-remote). ```json { "mcpServers": { "onepostly": { "command": "npx", "args": ["-y", "mcp-remote@latest", "https://mcp.onepostly.com"] } } } ``` To build your own client, follow the MCP authorization specification. A `401` response names the authorization server in its `WWW-Authenticate` header, and dynamic client registration is supported. Access tokens are OAuth tokens from this sign-in. API keys do not work on the MCP server. ## Access Levels [#access-levels] You give read access, write access or both, and the consent screen shows which. If the app does not ask for a level, it gets both. | Scope | Consent screen | Tools | | --- | --- | --- | | `mcp:read` | Read your workspace | `accounts_list`, `publish_options`, `posts_list`, `posts_get`, `analytics_get`, `wallet_get` | | `mcp:write` | Publish, schedule, and delete | All tools, including `posts_create` and `posts_delete` | ## Manage and Revoke Access [#manage-and-revoke-access] Open **Settings → MCP Connections** in the dashboard to see every connected app and its access. Click **Revoke** to end an app's access right away. You then have to approve it again before it can use Onepostly. You also have to approve an app again when it has not connected for 30 days, or when the person who approved it leaves the workspace. ## Troubleshooting [#troubleshooting] | Error | Cause | Fix | | --- | --- | --- | | `401` Invalid access token | Access was never approved, or it [ended](#manage-and-revoke-access) | [Sign in again](#sign-in-again) | | `403` Insufficient scope | Only read access was approved | Remove the server, add it again and approve write access | | `400` Unsupported protocol version | Your app uses an MCP version other than `2025-11-25` | Update the app | | `402` Payment required | A [billing block](/docs/pricing#billing-blocks) stops every call | Fix it in **Settings → Billing** | | `429` Rate limited | The workspace reached its rate limit | [Wait](/docs/rate-limits#handle-429-responses) for the seconds in `Retry-After` | | No tools appear | The app did not reload its MCP configuration | Restart the app completely | ### Sign In Again [#sign-in-again] | App | What to do | | --- | --- | | Claude Code | Run `/mcp` and select **onepostly** | | Codex | Run `codex mcp login onepostly` | | Other apps | Remove the server and add it again | Errors from the tools themselves, such as `ACCOUNT_NOT_FOUND`, are listed in [Tools](/docs/mcp/tools#errors). # Tools (/docs/mcp/tools) Every tool the MCP server offers, with its inputs, outputs and errors. Your assistant reads the same definitions from the server, so use this page to check what a tool can do or to debug a call. Write tools need write access. See [Access Levels](/docs/mcp/setup#access-levels). Every tool returns a one-line summary, such as `Found 2 connected accounts.`, and a structured result. The **Output** of each tool below describes the structured result. Ids use the same prefixes as the REST API, such as `acc_` for accounts and `pst_` for posts. {/* Generated by generate-docs-data from the MCP tool registry. Do not edit by hand. */} ## Tool Catalog [#tool-catalog] | Tool | Access | Title | | --- | --- | --- | | [`accounts_list`](#accounts_list) | Read | List accounts | | [`publish_options`](#publish_options) | Read | Get publishing options | | [`posts_create`](#posts_create) | Write | Create posts | | [`posts_list`](#posts_list) | Read | List posts | | [`posts_get`](#posts_get) | Read | Get a post | | [`analytics_get`](#analytics_get) | Read | Get post analytics | | [`posts_delete`](#posts_delete) | Write | Delete a post | | [`wallet_get`](#wallet_get) | Read | Get wallet balance | ## accounts_list [#accounts_list] **List accounts** (Read). List the workspace's connected social accounts with their status. An account whose status is not active must be reconnected before you post to it. Call this first to get accountId values and to see which platforms are available. ### Input [#input] | Field | Type | Description | | ---------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | | `platform` | `"instagram" \| "facebook" \| "threads" \| "x" \| "linkedin" \| "youtube" \| "tiktok" \| "pinterest" \| "bluesky"` | Only accounts on this platform. One of instagram, facebook, threads, x, linkedin, youtube, tiktok, pinterest, bluesky. | ### Output [#output] | Field | Type | Description | | ----------------------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `accounts` (required) | `object[]` | The matching accounts. | | `accounts[].id` (required) | `string` | The account id. Pass it as accountId to the other tools. | | `accounts[].platform` (required) | `string` | The platform, such as "x". | | `accounts[].displayName` (required) | `string` | The account name on the platform. | | `accounts[].handle` (required) | `string` | The account handle, without a leading @. | | `accounts[].avatarUrl` (required) | `string \| null` | The profile image URL. | | `accounts[].status` (required) | `"active" \| "expired" \| "revoked" \| "error" \| string` | active works normally. expired, revoked and error need a reconnect before the account can publish again. expired also covers an authorization that ran out and cannot renew by itself. A disconnected account is no longer returned. The account.disconnected webhook sends it as a DisconnectedAccount. New values can be added, so handle a value you do not know. | ## publish_options [#publish_options] **Get publishing options** (Read). Get account-specific publishing requirements and allowed values before creating a post. Pinterest returns boards, TikTok returns privacy levels and interaction limits. Call this after accounts_list. ### Input [#input-1] | Field | Type | Description | | ---------------------- | -------- | ------------------------------ | | `accountId` (required) | `string` | Account id from accounts_list. | ### Output [#output-1] | Field | Type | Description | | --------------------------------- | --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `account` (required) | `object` | The account, in the same shape as in accounts_list. | | `account.id` (required) | `string` | The account id. Pass it as accountId to the other tools. | | `account.platform` (required) | `string` | The platform, such as "x". | | `account.displayName` (required) | `string` | The account name on the platform. | | `account.handle` (required) | `string` | The account handle, without a leading @. | | `account.avatarUrl` (required) | `string \| null` | The profile image URL. | | `account.status` (required) | `"active" \| "expired" \| "revoked" \| "error" \| string` | active works normally. expired, revoked and error need a reconnect before the account can publish again. expired also covers an authorization that ran out and cannot renew by itself. A disconnected account is no longer returned. The account.disconnected webhook sends it as a DisconnectedAccount. New values can be added, so handle a value you do not know. | | `required` (required) | `string[]` | The options you have to send for this account. ["pinterest.boardId"] for Pinterest, ["tiktok.privacyLevel", "tiktok.allowComment", "tiktok.allowDuet", "tiktok.allowStitch"] for TikTok, and empty for other platforms. TikTok photo posts take allowComment only, without allowDuet or allowStitch. | | `options` (required) | `object` | | | `options.boards` | `object[]` | Pinterest only. The boards you can pass as pinterest.boardId. | | `options.privacyLevelOptions` | `("public_to_everyone" \| "mutual_follow_friends" \| "follower_of_creator" \| "self_only")[]` | TikTok only. The values the account accepts for tiktok.privacyLevel. | | `options.commentDisabled` | `boolean` | TikTok only. Comments are turned off for the account. Send tiktok.allowComment false, because true returns INTERACTION_DISABLED. | | `options.duetDisabled` | `boolean` | TikTok only. Duets are turned off for the account. Send tiktok.allowDuet false, because true returns INTERACTION_DISABLED. | | `options.stitchDisabled` | `boolean` | TikTok only. Stitches are turned off for the account. Send tiktok.allowStitch false, because true returns INTERACTION_DISABLED. | | `options.maxVideoPostDurationSec` | `number \| null` | TikTok only. The longest video the account can post, in seconds. | ## posts_create [#posts_create] **Create posts** (Write). Publish now or schedule for later on one or more accounts in one call; each account gets its own post. Platform options go under the account's platform key, such as tiktok for a TikTok account. Pass clientRequestId to make retries safe. ### Input [#input-2] | Field | Type | Description | | --------------------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `string` | The post text. Each account's platform limit applies, such as 500 characters on Threads. A longer text returns VALIDATION_ERROR. Default `""`. | | `mediaKind` | `"text" \| "image" \| "multi_image" \| "video" \| "reel" \| "document" \| "stories"` | What the media is. Optional for text posts and for one image, video or document, where the file shows its kind. Required for stories and for a Facebook reel. On Instagram, video and reel both publish a reel. | | `media` | `object[]` | Media files, in order. Each platform's own cap on the number of files applies. Default `[]`. | | `media[].id` | `string` | A media asset uploaded with Create Media. | | `media[].url` | `string` | A public HTTPS URL of the file. | | `thread` | `object[]` | X, Threads and Bluesky. Posts published as replies under the first one, in order. | | `thread[].text` | `string` | Text of the reply. Each account's platform limit applies. Default `""`. | | `thread[].media` | `object[]` | Media files of the reply, in order. Default `[]`. | | `scheduledFor` | `string` | Local date and time to publish, such as 2027-03-15T09:00:00, without Z or an offset. Omit it to publish now. | | `timezone` | `string` | IANA timezone of scheduledFor, such as America/New_York. Defaults to UTC. | | `accounts` (required) | `object[]` | Accounts to publish to, up to 50. Each account gets its own post. | | `accounts[].accountId` (required) | `string` | An account id from List Accounts. | | `accounts[].text` | `string` | Text for this account only. Defaults to the post text. | | `accounts[].x` | `object` | Options for X accounts. | | `accounts[].instagram` | `object` | Options for Instagram accounts. | | `accounts[].facebook` | `object` | Options for Facebook accounts. | | `accounts[].threads` | `object` | Options for Threads accounts. | | `accounts[].linkedin` | `object` | Options for LinkedIn accounts. | | `accounts[].youtube` | `object` | Options for YouTube accounts. | | `accounts[].tiktok` | `object` | Options for TikTok accounts. | | `accounts[].pinterest` | `object` | Options for Pinterest accounts. | | `accounts[].bluesky` | `object` | Options for Bluesky accounts. | | `clientRequestId` | `string` | Idempotency key. Repeating the same key in the same workspace returns the first call's posts instead of publishing again. | ### Output [#output-2] | Field | Type | Description | | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `groupId` (required) | `string` | The id shared by the posts of this call. Pass it to posts_list to read them back. | | `posts` (required) | `object[]` | One post per account. The status is "publishing" for a post that goes out now and "scheduled" for a scheduled one. | | `posts[].id` (required) | `string` | | | `posts[].groupId` (required) | `string \| null` | Shared by the posts one Create Post request made. Null for posts published outside Onepostly. | | `posts[].accountId` (required) | `string` | | | `posts[].platform` (required) | `"x" \| "instagram" \| "facebook" \| "threads" \| "linkedin" \| "youtube" \| "tiktok" \| "pinterest" \| "bluesky" \| string` | The platform id. New platforms can be added, so handle a value you do not know. | | `posts[].source` (required) | `"onepostly" \| "external"` | external for a post the account published outside Onepostly. | | `posts[].status` (required) | `"scheduled" \| "publishing" \| "published" \| "failed" \| "cancelled" \| "deleted" \| string` | scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know. | | `posts[].text` (required) | `string \| null` | The post's text. Null for posts published outside Onepostly. | | `posts[].mediaKind` (required) | `"text" \| "image" \| "multi_image" \| "video" \| "reel" \| "document" \| "stories" \| string` | What the media is. New values can be added, so handle a value you do not know. | | `posts[].media` (required) | `object[]` | The post's media files, in order. | | `posts[].thread` (required) | `object[]` | Replies published under the first post, in order. | | `posts[].scheduledFor` (required) | `string \| null` | Local date and time of the schedule in timezone. Null when not scheduled. | | `posts[].timezone` (required) | `string \| null` | IANA timezone of scheduledFor. Null when not scheduled. | | `posts[].options` (required) | `object` | The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know. | | `posts[].platformPostId` (required) | `string \| null` | The platform's own id for the post. Null until it is published. | | `posts[].url` (required) | `string \| null` | Public link to the post on the platform. | | `posts[].error` (required) | `object \| null` | Why the post failed. Null otherwise. | | `posts[].publishedAt` (required) | `string \| null` | When the post went live on the platform. Null until then. | | `posts[].metrics` (required) | `object \| null` | Lifetime metrics, or null before the first reading. | | `posts[].createdAt` (required) | `string` | | | `posts[].updatedAt` (required) | `string` | | | `replayed` (required) | `boolean` | true when the clientRequestId was used before and the earlier posts were returned. | ## posts_list [#posts_list] **List posts** (Read). List the workspace's posts newest first, one per account. Filter by status, platform, account, profile, or the group one posts_create call made. ### Input [#input-3] | Field | Type | Description | | ----------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | | `status` | `"scheduled" \| "publishing" \| "published" \| "failed" \| "cancelled" \| "deleted"` | Only posts with this status, for example failed or scheduled. | | `platform` | `"instagram" \| "facebook" \| "threads" \| "x" \| "linkedin" \| "youtube" \| "tiktok" \| "pinterest" \| "bluesky"` | Only posts on this platform. | | `accountId` | `string` | Only posts of this account. | | `profile` | `string` | Only posts of accounts filed under the profile with this name. Letter case does not matter. Use none for accounts without a profile. | | `groupId` | `string` | Only the posts one posts_create call made. | | `limit` | `integer` | Page size. Default `50`. | | `cursor` | `string` | nextCursor of the previous page. | ### Output [#output-3] | Field | Type | Description | | ----------------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `posts` (required) | `object[]` | The posts on this page, without media, thread, options and metrics. Call posts_get for those. | | `posts[].id` (required) | `string` | The post id. | | `posts[].groupId` (required) | `string \| null` | Shared by the posts of one posts_create call. Null for posts made outside Onepostly. | | `posts[].accountId` (required) | `string` | The account the post belongs to. | | `posts[].platform` (required) | `string` | The platform. | | `posts[].source` (required) | `"onepostly" \| "external"` | external for a post the account made outside Onepostly. | | `posts[].status` (required) | `"scheduled" \| "publishing" \| "published" \| "failed" \| "cancelled" \| "deleted" \| string` | scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know. | | `posts[].text` (required) | `string \| null` | The post text. | | `posts[].mediaKind` (required) | `"text" \| "image" \| "multi_image" \| "video" \| "reel" \| "document" \| "stories" \| string` | What the media is. New values can be added, so handle a value you do not know. | | `posts[].scheduledFor` (required) | `string \| null` | The scheduled local time, or null for a post that went out right away. | | `posts[].timezone` (required) | `string \| null` | The time zone of scheduledFor. | | `posts[].platformPostId` (required) | `string \| null` | The platform's id for the published post. | | `posts[].url` (required) | `string \| null` | The link to the published post, when the platform has one. | | `posts[].error` (required) | `object \| null` | Why the post failed. | | `posts[].publishedAt` (required) | `string \| null` | When the platform published the post. | | `posts[].createdAt` (required) | `string` | When the post was created. | | `nextCursor` (required) | `string \| null` | Pass it as cursor to get the next page. | | `hasMore` (required) | `boolean` | true when there is another page. | ## posts_get [#posts_get] **Get a post** (Read). Get one post with its status, link on the platform, and failure reason. ### Input [#input-4] | Field | Type | Description | | ------------------- | -------- | ---------------------------------------- | | `postId` (required) | `string` | Post id from posts_create or posts_list. | ### Output [#output-4] | Field | Type | Description | | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `post` (required) | `object` | | | `post.id` (required) | `string` | | | `post.groupId` (required) | `string \| null` | Shared by the posts one Create Post request made. Null for posts published outside Onepostly. | | `post.accountId` (required) | `string` | | | `post.platform` (required) | `"x" \| "instagram" \| "facebook" \| "threads" \| "linkedin" \| "youtube" \| "tiktok" \| "pinterest" \| "bluesky" \| string` | The platform id. New platforms can be added, so handle a value you do not know. | | `post.source` (required) | `"onepostly" \| "external"` | external for a post the account published outside Onepostly. | | `post.status` (required) | `"scheduled" \| "publishing" \| "published" \| "failed" \| "cancelled" \| "deleted" \| string` | scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know. | | `post.text` (required) | `string \| null` | The post's text. Null for posts published outside Onepostly. | | `post.mediaKind` (required) | `"text" \| "image" \| "multi_image" \| "video" \| "reel" \| "document" \| "stories" \| string` | What the media is. New values can be added, so handle a value you do not know. | | `post.media` (required) | `object[]` | The post's media files, in order. | | `post.thread` (required) | `object[]` | Replies published under the first post, in order. | | `post.scheduledFor` (required) | `string \| null` | Local date and time of the schedule in timezone. Null when not scheduled. | | `post.timezone` (required) | `string \| null` | IANA timezone of scheduledFor. Null when not scheduled. | | `post.options` (required) | `object` | The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know. | | `post.platformPostId` (required) | `string \| null` | The platform's own id for the post. Null until it is published. | | `post.url` (required) | `string \| null` | Public link to the post on the platform. | | `post.error` (required) | `object \| null` | Why the post failed. Null otherwise. | | `post.publishedAt` (required) | `string \| null` | When the post went live on the platform. Null until then. | | `post.metrics` (required) | `object \| null` | Lifetime metrics, or null before the first reading. | | `post.createdAt` (required) | `string` | | | `post.updatedAt` (required) | `string` | | ## analytics_get [#analytics_get] **Get post analytics** (Read). Get a post's lifetime metrics such as likes, impressions, comments, shares and views. ### Input [#input-5] | Field | Type | Description | | ------------------- | -------- | ---------------------------------------- | | `postId` (required) | `string` | Post id from posts_create or posts_list. | ### Output [#output-5] | Field | Type | Description | | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `postId` (required) | `string` | | | `accountId` (required) | `string` | | | `platform` (required) | `"x" \| "instagram" \| "facebook" \| "threads" \| "linkedin" \| "youtube" \| "tiktok" \| "pinterest" \| "bluesky" \| string` | The platform id. New platforms can be added, so handle a value you do not know. | | `status` (required) | `"ready" \| "pending" \| "failed" \| "unsupported" \| "unavailable" \| string` | ready has metrics. pending waits for the platform's first reading. failed means the last reading failed, and error says why. unavailable means the post can never be measured, because it is not published or the platform never reports metrics for it, such as a deleted post or a TikTok post that is not public. unsupported means the platform has no post metrics. unavailable and unsupported are final. New values can be added, so handle a value you do not know. | | `metrics` (required) | `object` | Lifetime metrics. A metric the platform does not report is null. | | `metrics.impressions` (required) | `integer \| null` | | | `metrics.reach` (required) | `integer \| null` | | | `metrics.likes` (required) | `integer \| null` | | | `metrics.comments` (required) | `integer \| null` | | | `metrics.shares` (required) | `integer \| null` | | | `metrics.saves` (required) | `integer \| null` | | | `metrics.views` (required) | `integer \| null` | | | `metrics.engagement` (required) | `integer \| null` | | | `fetchedAt` (required) | `string \| null` | When the platform was last read. Null before the first reading, and for X, which is read when you ask. | | `error` (required) | `object \| null` | Why the last reading failed. Null otherwise. | | `error.code` (required) | `"VALIDATION_ERROR" \| "INVALID_CURSOR" \| "UNAUTHORIZED" \| "FORBIDDEN" \| "GROUP_DISABLED" \| "NOT_FOUND" \| "IDEMPOTENCY_KEY_REUSED" \| "IDEMPOTENCY_KEY_IN_USE" \| "RATE_LIMITED" \| "QUOTA_EXCEEDED" \| "INTERNAL_SERVER_ERROR" \| "SERVICE_UNAVAILABLE" \| "PAYMENT_METHOD_REQUIRED" \| "PAYMENT_PAST_DUE" \| "INSUFFICIENT_WALLET" \| "USAGE_BILLING_REQUIRED" \| "USAGE_BILLING_FAILED" \| "ACCOUNT_NOT_FOUND" \| "CONNECTION_INACTIVE" \| "CONNECTION_BROKEN" \| "TOKEN_INVALID" \| "TOKEN_EXPIRED" \| "PERMISSION_DENIED" \| "ACCOUNT_RESTRICTED" \| "ACCOUNT_SUSPENDED" \| "AUTH_FAILED" \| "CONNECT_FAILED" \| "RECONNECT_MISMATCH" \| "BLUESKY_RECONNECT_APP_PASSWORD" \| "INVALID_REDIRECT_URL" \| "REDIRECT_URL_REQUIRED" \| "INVALID_CONNECT_SESSION" \| "FACEBOOK_PAGES_FAILED" \| "INSTAGRAM_ACCOUNTS_FAILED" \| "PAGE_NOT_FOUND" \| "PLATFORM_MAINTENANCE" \| "PROFILE_IN_USE" \| "PROFILE_NAME_TAKEN" \| "PROFILE_NOT_FOUND" \| "UNSUPPORTED_PLATFORM" \| "STATS_FAILED" \| "LIST_FAILED" \| "REVIEWS_FAILED" \| "PROFILE_FAILED" \| "CREATOR_INFO_FAILED" \| "BOARDS_FAILED" \| "BOARD_CREATE_FAILED" \| "SANDBOX_MISMATCH" \| "UNSUPPORTED_MEDIA_TYPE" \| "MEDIA_NOT_FOUND" \| "MEDIA_NOT_UPLOADED" \| "MEDIA_TYPE_MISMATCH" \| "MEDIA_TOO_LARGE" \| "MEDIA_UNFETCHABLE" \| "INVALID_MEDIA" \| "MEDIA_REQUIRED" \| "MEDIA_UPLOAD_FAILED" \| "MEDIA_PROCESSING_FAILED" \| "MEDIA_PROCESSING_TIMEOUT" \| "CONTAINER_FAILED" \| "URL_OWNERSHIP_UNVERIFIED" \| "REEL_UPLOAD_FAILED" \| "STORY_UPLOAD_FAILED" \| "PUBLISH_FAILED" \| "PUBLISH_INTERRUPTED" \| "PLATFORM_UNAVAILABLE" \| "POST_NOT_PUBLISHED" \| "TEXT_TOO_LONG" \| "TEXT_REQUIRED" \| "CAPTION_TOO_LONG" \| "INVALID_FIRST_COMMENT" \| "INVALID_AI_LABEL" \| "UNSUPPORTED_MEDIA_KIND" \| "UNSUPPORTED_FEATURE" \| "INVALID_MULTI_IMAGE" \| "DUPLICATE_CONTENT" \| "GEO_RESTRICTION_FAILED" \| "INVALID_LINK" \| "INVALID_QUOTE" \| "INVALID_REPLY" \| "INVALID_TOPIC_TAG" \| "INVALID_AUDIO" \| "INVALID_SPONSOR" \| "INVALID_TRIAL_REEL" \| "INVALID_CAROUSEL" \| "TEXT_FORMAT_UNSUPPORTED" \| "PRIVACY_LEVEL_REQUIRED" \| "INVALID_PRIVACY_LEVEL" \| "INTERACTION_DISABLED" \| "SPAM_RISK" \| "POSTING_LIMIT_REACHED" \| "CAPACITY_LIMITED" \| "UPLOAD_LIMIT_EXCEEDED" \| "NOT_EDITABLE" \| "POST_PUBLISHING" \| "NOT_DELETABLE" \| "DELETE_FAILED" \| "DELETE_PERMISSION" \| "THREAD_DELETE_PARTIAL" \| "MEDIA_DELETE_UNSUPPORTED" \| "INVALID_EXTERNAL_ID" \| "NOT_PUBLISHED" \| "ACCOUNT_REQUIRED" \| "AMBIGUOUS_TARGET" \| "POST_ACCOUNT_MISMATCH" \| "TARGET_SYNC_FAILED" \| "MISSING_EXTERNAL_ID" \| "NOT_A_COMMENT" \| "COMMENT_CREATE_FAILED" \| "COMMENT_DELETE_FAILED" \| "COMMENT_HIDE_FAILED" \| "COMMENT_LIKE_FAILED" \| "COMMENT_UNLIKE_FAILED" \| "PRIVATE_REPLY_FAILED" \| "COMMENTS_PERMISSION" \| "COMMENTS_UNSUPPORTED" \| "UNSUPPORTED_MEDIA" \| "COMMENTS_FAILED" \| "INVALID_PARENT" \| "INVALID_COMMENT_ID" \| "RESOLVE_FAILED" \| "ENGAGEMENT_FAILED" \| "ENGAGEMENT_PERMISSION" \| "LIKE_FAILED" \| "UNLIKE_FAILED" \| "BOOKMARK_FAILED" \| "UNBOOKMARK_FAILED" \| "REPOST_FAILED" \| "UNREPOST_FAILED" \| "REPOST_PERMISSION" \| "UNREPOST_PERMISSION" \| "UNREPOST_REQUIRES_REPOST_ID" \| "REPOSTS_UNSUPPORTED" \| "REPOSTS_UNAUTHORIZED" \| "REPOSTS_FAILED" \| "READ_FAILED" \| "SYNC_FAILED" \| "CONVO_NOT_FOUND" \| "RECIPIENT_NOT_FOUND" \| "RECIPIENT_UNREACHABLE" \| "MESSAGE_WINDOW_EXPIRED" \| "CONVO_LOCKED" \| "INBOX_PERMISSION" \| "INBOX_FAILED" \| "INVALID_ATTACHMENT" \| "ATTACHMENT_UNSUPPORTED" \| "TEMPLATE_UNSUPPORTED" \| "INVALID_TEMPLATE" \| "LIMIT_REACHED" \| "CONFLICT" \| "INVALID_RANGE" \| "TIMELINE_UNSUPPORTED" \| "ANALYTICS_PERMISSION" \| "ANALYTICS_FAILED" \| "ANALYTICS_PENDING" \| "POST_NOT_FOUND" \| "VIDEO_ID_PENDING" \| "VIDEO_NOT_FOUND" \| "PRIVACY_RESTRICTED" \| "CREATE_FAILED" \| "DELIVERY_IN_PROGRESS" \| string` | Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes. | | `error.message` (required) | `string` | Human-readable reason for display. | ## posts_delete [#posts_delete] **Delete a post** (Write). Cancel a post that has not been published yet, or delete a published post from its platform. ### Input [#input-6] | Field | Type | Description | | ------------------- | -------- | -------------------------------------------------------------------------------------- | | `postId` (required) | `string` | Post id. A scheduled post is cancelled; a published post is deleted from the platform. | ### Output [#output-6] | Field | Type | Description | | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `post` (required) | `object` | | | `post.id` (required) | `string` | | | `post.groupId` (required) | `string \| null` | Shared by the posts one Create Post request made. Null for posts published outside Onepostly. | | `post.accountId` (required) | `string` | | | `post.platform` (required) | `"x" \| "instagram" \| "facebook" \| "threads" \| "linkedin" \| "youtube" \| "tiktok" \| "pinterest" \| "bluesky" \| string` | The platform id. New platforms can be added, so handle a value you do not know. | | `post.source` (required) | `"onepostly" \| "external"` | external for a post the account published outside Onepostly. | | `post.status` (required) | `"scheduled" \| "publishing" \| "published" \| "failed" \| "cancelled" \| "deleted" \| string` | scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know. | | `post.text` (required) | `string \| null` | The post's text. Null for posts published outside Onepostly. | | `post.mediaKind` (required) | `"text" \| "image" \| "multi_image" \| "video" \| "reel" \| "document" \| "stories" \| string` | What the media is. New values can be added, so handle a value you do not know. | | `post.media` (required) | `object[]` | The post's media files, in order. | | `post.thread` (required) | `object[]` | Replies published under the first post, in order. | | `post.scheduledFor` (required) | `string \| null` | Local date and time of the schedule in timezone. Null when not scheduled. | | `post.timezone` (required) | `string \| null` | IANA timezone of scheduledFor. Null when not scheduled. | | `post.options` (required) | `object` | The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know. | | `post.platformPostId` (required) | `string \| null` | The platform's own id for the post. Null until it is published. | | `post.url` (required) | `string \| null` | Public link to the post on the platform. | | `post.error` (required) | `object \| null` | Why the post failed. Null otherwise. | | `post.publishedAt` (required) | `string \| null` | When the post went live on the platform. Null until then. | | `post.metrics` (required) | `object \| null` | Lifetime metrics, or null before the first reading. | | `post.createdAt` (required) | `string` | | | `post.updatedAt` (required) | `string` | | ## wallet_get [#wallet_get] **Get wallet balance** (Read). Get the workspace's prepaid wallet balance in US dollars. X posts, deletes and analytics reads are paid from it, and fail with INSUFFICIENT_WALLET when it is too low. ### Input [#input-7] None. ### Output [#output-7] | Field | Type | Description | | --------------------- | -------- | ----------------------------------------------------- | | `balance` (required) | `string` | The balance in US dollars, with three decimal places. | | `currency` (required) | `"usd"` | Always usd. | ## Media Rules [#media-rules] `posts_create` takes the same body as [Create Post](/docs/api-reference/posts/create-post), plus a `clientRequestId` that makes a retried call safe. Calling it again with the same `clientRequestId` returns the first call's posts with `replayed: true`, and nothing is published twice. See [Create Posts](/docs/publishing) for how posts behave. Each `mediaKind` takes a set number of files in `media`. | `mediaKind` | Publishes | `media` | Platforms | | ------------- | ------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------ | | `text` | A text-only post | None | X, Facebook, Threads, LinkedIn, Bluesky | | `image` | One image | Exactly 1 | X, Instagram, Facebook, Threads, LinkedIn, TikTok, Pinterest, Bluesky | | `multi_image` | A carousel or image set | 2 or more, up to the platform maximum | X, Instagram, Facebook, Threads, LinkedIn, TikTok, Bluesky | | `video` | One video. On Instagram, a Reel | Exactly 1 | X, Instagram, Facebook, Threads, LinkedIn, YouTube, TikTok, Pinterest, Bluesky | | `reel` | A Reel | Exactly 1 | Instagram, Facebook | | `document` | A document post | Exactly 1 | LinkedIn | | `stories` | A story | Exactly 1 | Instagram, Facebook | Which kinds each platform accepts is in [Compare Platforms](/docs/platforms#post-types). Media URLs have to meet the [media URL requirements](/docs/media-uploads#media-url-requirements). The server has no upload tool, so upload files as described in [Media](/docs/media-uploads) first. ## Account Fields [#account-fields] Each entry in `accounts` takes an `accountId`. It can also take its own `text`, which replaces the post text for that account, and options for its platform under the platform's name, such as `{ "pinterest": { "boardId": "…" } }`. Every option per platform is on that platform's page, such as [Pinterest](/docs/pinterest#publish). An unknown field, or options for another platform, fails with `VALIDATION_ERROR`. A `publishing` post has not reached the platform yet. Call `posts_get` until it is `published` or `failed`. See [Post Status](/docs/post-lifecycle#post-status). `posts_delete` cancels a post that is not published yet, or deletes a published post from its platform, including the rest of its thread. The post stays in Onepostly as `cancelled` or `deleted`. Calling it again on a post that is already `cancelled` or `deleted` succeeds and returns the post as it is. Which platforms support deleting is in [Compare Platforms](/docs/platforms#capabilities). `wallet_get` returns the balance that pays for X posts, deletes and analytics reads. See [X Wallet](/docs/pricing#x-wallet). ## Examples [#examples] Publish a text post now. ```json { "text": "Spring collection is live.", "accounts": [{ "accountId": "acc_YOUR_X_ACCOUNT_ID" }] } ``` Schedule an image post with a `clientRequestId`, so a retry does not post twice. ```json { "text": "Doors open at 9.", "media": [{ "url": "https://cdn.onepostly.com/media/storefront.jpg" }], "scheduledFor": "2027-03-15T09:00:00", "timezone": "America/New_York", "clientRequestId": "launch-post-2027-03-15", "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID" }, { "accountId": "acc_YOUR_PINTEREST_ACCOUNT_ID", "pinterest": { "boardId": "1084523710032119087" } } ] } ``` This is the `publish_options` output for a TikTok account. ```json { "account": { "id": "acc_5a2d9c1e7b4f4e83a6d03c8b1f9e2a74", "platform": "tiktok", "displayName": "Acme", "handle": "acme", "avatarUrl": null, "status": "active" }, "required": [ "tiktok.privacyLevel", "tiktok.allowComment", "tiktok.allowDuet", "tiktok.allowStitch" ], "options": { "privacyLevelOptions": ["public_to_everyone", "mutual_follow_friends", "self_only"], "commentDisabled": false, "duetDisabled": false, "stitchDisabled": true, "maxVideoPostDurationSec": 600 } } ``` This is a `posts_get` result for a post published to X. ```json { "post": { "id": "pst_c27a9e4b6f134d8aa5b29e0d1f3c7a64", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_3f6c2a915d4e4b7a9e1f8a2b6c0d4e57", "platform": "x", "source": "onepostly", "status": "published", "text": "Spring collection is live. Free shipping through Sunday.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "1899745123456789012", "url": "https://x.com/i/web/status/1899745123456789012", "error": null, "publishedAt": "2027-03-15T09:00:05.402Z", "metrics": null, "createdAt": "2027-03-15T09:00:02.114Z", "updatedAt": "2027-03-15T09:00:06.871Z" } } ``` Every analytics status and which metrics each platform reports are in [Analytics Status](/docs/analytics#analytics-status). ## Errors [#errors] A failed call returns a tool result marked as an error. Its text is a JSON object with a `code`, a `message` and an HTTP-style `status`. A `hint` with the next step is added when it helps. For invalid arguments, `issues` lists every problem with the `param` at fault. ```json { "error": { "code": "VALIDATION_ERROR", "message": "Invalid tool arguments.", "status": 400, "issues": [ { "param": "accounts[0].accountId", "code": "invalid_type", "message": "Invalid input: expected string, received undefined" } ] } } ``` | Code | Cause | Fix | | --- | --- | --- | | `VALIDATION_ERROR` | An argument is missing or invalid, an id has the wrong prefix, the text is too long for a platform, or an account has an option or `mediaKind` its platform does not accept | Fix what `issues` or the message names, then call again | | `INVALID_CURSOR` | `cursor` is not a `nextCursor` from `posts_list` | Pass the `nextCursor` of the previous page, or leave `cursor` out | | `ACCOUNT_NOT_FOUND` | The `accountId` is not a connected account in this workspace | Call `accounts_list` and use an id from it | | `CONNECTION_INACTIVE` | The account is not active | [Reconnect the account](/docs/account-status#reconnect-an-account) | | `NOT_FOUND` | There is no post with this `postId` in the workspace | Call `posts_list` to find the post | | `MEDIA_NOT_FOUND` | A `media[].id` is not a media file in this workspace | Upload the file with the Media API and use its id | | `OPTIONS_UNAVAILABLE` | The platform did not return the account's boards or creator settings | Call `publish_options` again later | | `RATE_LIMITED` | The account reached its publishing limit. `details.retryAfterSeconds` says how long to wait | Wait that long, or schedule the post for later. See [Rate Limits](/docs/rate-limits) | | `POST_PUBLISHING` | `posts_delete` was called while the post is being published | Call again once `posts_get` shows a final status | | `NOT_DELETABLE` | There is nothing on the platform to delete. The post failed before reaching it, or was made outside Onepostly | Check the post with `posts_get` | | `UNSUPPORTED_PLATFORM` | The post's platform does not support deleting | Delete the post in the platform's app | | `INSUFFICIENT_WALLET` | The wallet balance does not cover the X posts of `posts_create`, an X delete, or the day's read of an X post in `analytics_get`. Nothing is created or changed. A scheduled X post is charged when it publishes, and `posts_get` shows it `failed` with this code if the balance no longer covers it then | Top up the wallet in **Settings → Wallet**, then call again | | `TOKEN_INVALID` | The platform rejected the account's access | [Reconnect the account](/docs/account-status#reconnect-an-account) | | `PLATFORM_UNAVAILABLE` | The platform did not respond in time | Call again | | `DELETE_PERMISSION` | The account cannot delete this post | Reconnect the account and approve every permission, or check that the account owns the post | | `DELETE_FAILED` | The platform failed the delete | Call again later, or delete the post in the platform's app | | `TOOL_ERROR` | The call failed unexpectedly | Call again. For `posts_create`, reuse the same `clientRequestId` so the post is not created twice | Other codes are the same as in the REST API. See [Error Codes](/docs/error-handling#error-codes). # Media (/docs/media-uploads) Upload a file and attach it to your post, or use a public HTTPS URL that meets the [Media URL Requirements](#media-url-requirements). ## Upload a File [#upload-a-file] ### Create the Media Item [#create-the-media-item] Send the file name, its type and its exact size in bytes. The type is one of the [Supported Formats](#supported-formats), and the size has to be within its limit. **TypeScript** ```typescript import { Configuration, MediaApi } from "@onepostly/sdk"; const mediaApi = new MediaApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await mediaApi.createMedia({ createMediaBody: { "filename": "launch.mp4", "contentType": "video/mp4", "size": 48203776 }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.media_api import MediaApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: media_api = MediaApi(api_client) response = await media_api.create_media( create_media_body={ "filename": "launch.mp4", "contentType": "video/mp4", "size": 48203776 }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/media" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "filename": "launch.mp4", "contentType": "video/mp4", "size": 48203776 }' ``` **Response** ```json { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b", "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a0b.mp4", "contentType": "video/mp4", "sizeBytes": null, "filename": "launch.mp4", "status": "pending", "createdAt": "2027-03-15T09:00:00.000Z", "uploadUrl": "https://5d1e8a3c9f2b4e7a.r2.cloudflarestorage.com/onepostly-media/temp/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a0b.mp4?X-Amz-Expires=3600&X-Amz-Date=20270315T090000Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=EXAMPLEKEY%2F20270315%2Fauto%2Fs3%2Faws4_request&X-Amz-SignedHeaders=content-length%3Bcontent-type%3Bhost&X-Amz-Signature=0f4c2b9e7a1d3f5b8c6e0a2d4f6b8e1c3a5d7f9b2e4c6a8d0f1b3e5c7a9d2f4b", "uploadExpiresIn": 3600 } ``` The response is `201` with the new media item. | Field | Description | | --- | --- | | `id` | The id you use in a post | | `url` | The file's public URL. It never changes, and serves the file once `status` is `ready` | | `status` | `pending` until the file arrives and is checked, then `ready` | | `sizeBytes` | The file size, `null` until `status` is `ready` | | `uploadUrl` | Where you send the file | | `uploadExpiresIn` | Seconds until `uploadUrl` stops working, `3600` | ### Upload the File [#upload-the-file] Send the file with a `PUT` request to `uploadUrl`. You do not need an API key, because the URL itself allows the upload. The `Content-Type` header has to match the `contentType` you sent in step 1, and the file has to be exactly `size` bytes. Send the whole file in one request. Your HTTP client sets `Content-Length` from the file, as in the examples below. Any other length is refused with `403`, and nothing is stored. To upload a different file, create a new media item. **TypeScript** ```ts import { readFile } from "node:fs/promises"; await fetch(uploadUrl, { method: "PUT", headers: { "Content-Type": "video/mp4" }, body: await readFile("launch.mp4"), }); ``` **Python** ```python import httpx with open("launch.mp4", "rb") as f: httpx.put(upload_url, content=f.read(), headers={"Content-Type": "video/mp4"}) ``` **cURL** ```bash curl -X PUT "$UPLOAD_URL" \ -H "Content-Type: video/mp4" \ --data-binary @launch.mp4 ``` Each upload is checked against the type and size you declared, usually within seconds. To see the result, call `GET /v1/media/{id}`, which also checks the file if that has not happened yet. A checked file shows the status `ready` and its size in `sizeBytes`, and `url` serves it from then on. ### Use It in a Post [#use-it-in-a-post] Put the id in `media`. See [Create Posts](/docs/publishing) for the full request. **TypeScript** ```typescript 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": "Launch day", "media": [ { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Launch day", "media": [ { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Launch day", "media": [ { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "Launch day", "mediaKind": "video", "media": [ { "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a0b.mp4" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T10:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } ] } ``` In `media` and `thread[].media`, each item takes an `id` or a `url`, not both. The post shows every file by its `url`, even one you sent by `id`. The files set the post kind. One video makes a video post, and several files make a `multi_image` post. For a Facebook `reel` and for `stories`, set `mediaKind` yourself. See [Media Kinds](/docs/publishing#media-kinds) for the full list. ### Expiry [#expiry] | File | Kept for | | --- | --- | | `uploadUrl` | 1 hour | | A file no post uses | 7 days | | A file in a scheduled post | Until the post publishes | | A file in a published post | No expiry | An expired `uploadUrl` needs a new media item. ## Media URL Requirements [#media-url-requirements] Every `media` URL must meet these rules, uploaded or self-hosted. - HTTPS to a public address. - At most 2,048 characters. - Returns the file with `200`, `Content-Length` and the right `Content-Type`. - At most 5 redirects, each to a public HTTPS address. - No stall longer than 30 seconds. Share links from Google Drive, Dropbox, OneDrive, SharePoint and iCloud fail. They return a web page, not the file. Open the URL in a private window to check it. If you see a page, upload the file to Onepostly. The first two rules are checked when you create the post and return `400 VALIDATION_ERROR`. The rest are checked at publish and fail the post with `MEDIA_UNFETCHABLE`. Uploaded files meet every rule once their `status` is `ready`. ## Supported Formats [#supported-formats] Onepostly accepts these files, and each platform adds its own limits. See the media requirements on each platform page, such as [Instagram](/docs/instagram#media-requirements). | Format | `contentType` | Max size | |---|---|---| | JPEG | `image/jpeg` | 30 MB | | PNG | `image/png` | 30 MB | | GIF | `image/gif` | 30 MB | | WebP | `image/webp` | 30 MB | | MP4 | `video/mp4` | 1 GB | | MOV | `video/quicktime` | 1 GB | | AVI | `video/x-msvideo` or `video/avi` | 1 GB | | WebM | `video/webm` | 1 GB | | PDF | `application/pdf` | 100 MB | | PPT | `application/vnd.ms-powerpoint` | 100 MB | | PPTX | `application/vnd.openxmlformats-officedocument.presentationml.presentation` | 100 MB | | DOC | `application/msword` | 100 MB | | DOCX | `application/vnd.openxmlformats-officedocument.wordprocessingml.document` | 100 MB | A larger `size` is refused with `400 MEDIA_TOO_LARGE` before the upload starts. ## Media per Platform [#media-per-platform] The `mediaKind` values and the file count each platform takes. | Platform | `text` | `image` | `multi_image` | `video` | `reel` | `document` | `stories` | Max files | | ---------------------------- | ------ | ------- | ------------- | --------------- | ------ | ---------- | --------- | --------- | | [X (Twitter)](/docs/x) | Yes | Yes | Yes | Yes | No | No | No | 4 | | [Instagram](/docs/instagram) | No | Yes | Yes | Yes (As a reel) | Yes | No | Yes | 10 | | [Facebook](/docs/facebook) | Yes | Yes | Yes | Yes | Yes | No | Yes | 10 | | [Threads](/docs/threads) | Yes | Yes | Yes | Yes | No | No | No | 20 | | [LinkedIn](/docs/linkedin) | Yes | Yes | Yes | Yes | No | Yes | No | 20 | | [YouTube](/docs/youtube) | No | No | No | Yes | No | No | No | 1 | | [TikTok](/docs/tiktok) | No | Yes | Yes | Yes | No | No | No | 35 | | [Pinterest](/docs/pinterest) | No | Yes | No | Yes | No | No | No | 1 | | [Bluesky](/docs/bluesky) | Yes | Yes | Yes | Yes | No | No | No | 4 | Durations, sizes and dimensions are on each platform page, such as [X](/docs/x#media-requirements). See [Compare Platforms](/docs/platforms) to view all platforms side by side. ## List Uploads [#list-uploads] `GET /v1/media` lists the files you uploaded, newest first. Media items still waiting for their upload are not listed. **TypeScript** ```typescript import { Configuration, MediaApi } from "@onepostly/sdk"; const mediaApi = new MediaApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await mediaApi.listMedia({ limit: 20, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.media_api import MediaApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: media_api = MediaApi(api_client) response = await media_api.list_media( limit=20, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/media?limit=20" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b", "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a0b.mp4", "contentType": "video/mp4", "sizeBytes": 48203776, "filename": "launch.mp4", "status": "ready", "createdAt": "2027-03-15T09:00:00.000Z" }, { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a02", "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a02.jpg", "contentType": "image/jpeg", "sizeBytes": 482113, "filename": "spring.jpg", "status": "ready", "createdAt": "2027-03-14T16:30:00.000Z" } ], "nextCursor": null, "hasMore": false } ``` You get 50 files per page by default and up to 100 with `limit`. Pass `nextCursor` as `cursor` to get the next page, until `hasMore` is `false`. Add `include=total` to get the total count. See [Pagination](/docs/pagination). ## Delete an Upload [#delete-an-upload] **TypeScript** ```typescript import { Configuration, MediaApi } from "@onepostly/sdk"; const mediaApi = new MediaApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await mediaApi.deleteMedia({ id: "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.media_api import MediaApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: media_api = MediaApi(api_client) response = await media_api.delete_media( "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X DELETE "https://api.onepostly.com/v1/media/med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` This returns `204` and deletes the file for good. Published posts are not affected, because each platform keeps its own copy. A scheduled post that still uses the file fails when it publishes, so delete files only once all their posts are live. ## Errors [#errors] These come back from a media request or `POST /v1/posts`. | Code | HTTP | Cause | Fix | |---|---|---|---| | `VALIDATION_ERROR` | 400 | A field is missing or too long, a `media` item has both or neither of `id` and `url`, or a URL breaks the [rules](#media-url-requirements) | Fix the field in `param` | | `UNSUPPORTED_MEDIA_TYPE` | 400 | `contentType` is not [supported](#supported-formats) | Convert the file | | `MEDIA_TOO_LARGE` | 400 | `size` is over the [limit](#supported-formats) for `contentType` | Compress the file | | `NOT_FOUND` | 404 | No media item has this id | Check the id with `GET /v1/media` | | `MEDIA_NOT_FOUND` | 404 | A post's `media[].id` does not exist | Use an id from `GET /v1/media` | | `SERVICE_UNAVAILABLE` | 503 | Uploads are down for now | Try again later | File problems show up later, in the post's `error.code`. See [Failed Posts](/docs/post-lifecycle#failed-posts). | Code | Cause | Fix | |---|---|---| | `MEDIA_NOT_UPLOADED` | The file was never uploaded, or the upload expired | Upload the file, then create the post again | | `MEDIA_TYPE_MISMATCH` | The file's `Content-Type` is not its `contentType` | Create a new media item with the right type | | `MEDIA_UNFETCHABLE` | The URL breaks a [URL rule](#media-url-requirements) | Fix the URL | | `INVALID_MEDIA` | The file is empty, or the platform rejects it | Check the platform's Media Requirements | | `URL_OWNERSHIP_UNVERIFIED` | TikTok refuses the URL's domain | Upload the file and use its `id` | Other codes are in [Errors](/docs/error-handling#error-codes). # Pricing and Wallet (/docs/pricing) You pay for two things. Each connected account past the first 2 is billed by the day, on every platform. Actions on X are paid from a prepaid wallet, because X charges for every API call. Nothing else is billed. Posts, media, webhooks, analytics on other platforms and API requests are included. | What | How it is billed | Paid with | | --- | --- | --- | | Connected accounts | By the day, past the 2 free accounts | Your payment method | | X actions | Per action, at X's list prices | Your wallet balance | ## Free Accounts [#free-accounts] Every workspace gets 2 connected accounts for free, on any platforms. You need no payment method for them, and they stay free when you add more accounts. ## Account Pricing [#account-pricing] Each account past the free 2 is billed in tiers. The price is per account for 30 days, and each tier only prices the accounts that fall in it. | Connected accounts | Price per account per 30 days | | --- | --- | | 1 to 2 | Free | | 3 to 10 | $5 | | 11 to 100 | $3 | | 101 and more | $1 | For example, 12 connected accounts cost 8 × $5 plus 2 × $3, which is $46 for 30 days. 150 accounts cost $40 plus $270 plus $50, which is $360. | Rule | Detail | | --- | --- | | Billed by the day | Each day costs a 30th of the monthly price, for the most accounts connected that UTC day | | Disconnected accounts | They stop counting from the next UTC day | | Reconnects | A reconnect never adds a billed account | | Invoices | Under **Settings → Billing** in the dashboard | | Deleting the workspace | The usage so far is charged first. If that charge fails, the workspace stays | Only the workspace owner can see invoices and change the payment method. ### Charges [#charges] Your card is charged during a billing period as the usage grows, and once more when it ends. | Charge | When | | --- | --- | | First charge | The usage of the billing period reaches $10 | | Each later charge | The new usage reaches twice the previous charge, up to $5,120 | | Final charge | The 30-day period ends. It covers whatever is left | ## Payment Method [#payment-method] You need a payment method before you connect your 3rd account. Add it in the dashboard under **Settings → Billing**. Without one, a connect past the 2 free accounts goes like this. | Case | Result | | --- | --- | | Starting a connect | `402 USAGE_BILLING_REQUIRED`, before the user signs in | | More accounts than free slots | The free slots fill. The redirect has `skipped`, the number left out | | No account fits | The redirect has `error=USAGE_BILLING_REQUIRED` | | Billing fails | The account is not added. `402 USAGE_BILLING_FAILED`, or the same `error` on the redirect | Starting a connect means `POST /v1/connect-sessions`, or `POST /v1/accounts` for Bluesky. When billing fails after the sign-in, you may receive `account.connected` followed by `account.disconnected`. See [Redirect Errors](/docs/connection#redirect-errors) for the browser part of a connect. ## Billing Blocks [#billing-blocks] A workspace is blocked when it has 3 or more accounts and no payment method, or when an invoice stays unpaid after every payment attempt. While a payment is still being collected, everything keeps working. Fix both under **Settings → Billing**. | Code | When | What to do | | --- | --- | --- | | `PAYMENT_METHOD_REQUIRED` | 3 or more accounts and no payment method | Add a payment method | | `PAYMENT_PAST_DUE` | An invoice is unpaid after every payment attempt | Update the payment method and pay the invoice | While the workspace is blocked, this is what you observe. | Area | During the block | After billing is fixed | | --- | --- | --- | | API requests | Every API-key request returns `402`, reads included | Requests work again | | MCP server | Every request returns `402`, so no tool runs | Tools work again | | Scheduled posts | They stay `scheduled` and do not publish | Posts that came due publish | | Analytics | Metrics stop updating | Metrics update again | | Dashboard | You can sign in, see accounts, posts and logs, and fix billing | Everything works again | ## X Wallet [#x-wallet] X charges for every API call, so actions on X accounts are paid from your prepaid Onepostly wallet. Other platforms never use the wallet. ### X Prices [#x-prices] The wallet pays [X's list prices](https://docs.x.com/x-api/getting-started/pricing). When X changes its prices, the wallet follows. These are the current prices. | Action | Price | | --- | --- | | Publish a post, reply or quote | $0.015 | | Publish one with a URL in its text | $0.20 | | Like, repost or bookmark | $0.015 | | Unlike, undo a repost or remove a bookmark | $0.01 | | Delete a post or reply | $0.01 per post | | Read post analytics | $0.005 per post, at most once per UTC day | | List replies or reposters | $0.005 per page | ### When You Are Charged [#when-you-are-charged] Every X action is checked against the balance when you send the request, and charged when it runs. | Case | What happens | | --- | --- | | The balance is too low | `402 INSUFFICIENT_WALLET`. Nothing is created or changed | | A create with several X accounts | It is priced for all of them together | | A scheduled post | Checked when you create it, charged at its scheduled time | | Too low at the scheduled time | The post ends `failed` with `INSUFFICIENT_WALLET` | | An edit of an X post's text or thread | Checked again when you send it | | A thread | Charged per post. Deleting it is charged per post too | | X does not complete the action | The amount goes back to the wallet | | A thread fails partway | The posts that went live stay charged | | [Post analytics](/docs/x#analytics) | Read when you ask, at most once per post and UTC day. Only that read is charged | | A repeated like, repost or bookmark | Charged every time | | Listing recent posts or syncing | Free | After `INSUFFICIENT_WALLET`, top up and send the request again. ### Check the Balance [#check-the-balance] `GET /v1/wallet` returns the balance in US dollars. Any API key can call it, including a `read_only` key. **TypeScript** ```typescript import { Configuration, WalletApi } from "@onepostly/sdk"; const walletApi = new WalletApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await walletApi.getWalletBalance(); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.wallet_api import WalletApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: wallet_api = WalletApi(api_client) response = await wallet_api.get_wallet_balance() print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/wallet" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "balance": "12.345", "currency": "usd" } ``` `balance` is a decimal string with three decimal places, such as `"0.015"` for 1.5 cents. The MCP server has the same call as the `wallet_get` tool. ### Top Up [#top-up] The workspace owner tops up in the dashboard under **Settings → Wallet**, with a card. Every member of the workspace can see the balance and the top-up history there. ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `PAYMENT_METHOD_REQUIRED` | 402 | The workspace has 3 or more accounts and no payment method | Add a payment method | | `PAYMENT_PAST_DUE` | 402 | An invoice is unpaid after every payment attempt | Update the payment method and pay | | `USAGE_BILLING_REQUIRED` | 402 | A connect past the 2 free accounts, with no payment method | Add a payment method, then connect again | | `USAGE_BILLING_FAILED` | 402 | Billing for the new account failed, so it was not added | Check the payment method, then connect again | | `INSUFFICIENT_WALLET` | 402 | The wallet cannot pay for an X action | Top up, then retry | A scheduled X post the wallet cannot cover fails with `INSUFFICIENT_WALLET`. See [Errors](/docs/error-handling#billing-and-wallet). # Quickstart (/docs/quickstart) 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 [#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. ```bash export ONEPOSTLY_API_KEY="op_YOUR_KEY" ``` Every sample in these docs reads the key from `ONEPOSTLY_API_KEY`. See [Authentication](/docs/authentication) for headers and permissions. ### Install an SDK [#install-an-sdk] **TypeScript** ```bash npm install @onepostly/sdk ``` **Python** ```bash pip install onepostly ``` Prefer plain HTTP? Skip this step. Every sample has a cURL tab, and the base URL is `https://api.onepostly.com`. ### Connect an Account [#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. **TypeScript** ```typescript 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); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.list_accounts() print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "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 [#publish-a-post] Send the text and the account to publish to. **TypeScript** ```typescript 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); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Hello from Onepostly.", "accounts": [ { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Hello from Onepostly.", "accounts": [ { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID" } ] }' ``` **Response** ```json { "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`. ```json "media": [{ "url": "https://example.com/photo.jpg" }] ``` Posts on X are paid from your [wallet](/docs/pricing#x-wallet), so top it up first. ### Check the Result [#check-the-result] Read the post by its `id`. **TypeScript** ```typescript 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); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.get_post( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "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](/docs/webhooks). ## If It Fails [#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](/docs/error-handling). ## Next Steps [#next-steps] - [Create Posts](/docs/publishing): Cross-post, set options per account and list your posts. - [Media](/docs/media-uploads): Upload your own images and videos. - [Scheduling and Editing](/docs/scheduling): Publish later, edit or cancel a scheduled post. - [Webhooks](/docs/webhooks): Get notified when a post is published or fails. - [Connect Accounts](/docs/connection): Connect accounts in the dashboard, or let your users connect theirs. - [Compare Platforms](/docs/platforms): What each platform supports and how to connect it. # Account Webhooks (/docs/webhooks/accounts) Keep your account list current, and ask for a reconnect before scheduled posts fail. Each example is the [payload's](/docs/webhooks#payload) `data`. ## Events [#events] | Event | Fires when | | --- | --- | | `account.connected` | An account connects or reconnects | | `account.disconnected` | An account is disconnected | | `account.expiring` | An account that cannot auto-renew expires in 7 days | | `account.expired` | The account's access expired | | `account.revoked` | The platform or the owner withdrew access | After `account.expired` or `account.revoked`, the account cannot publish and its posts fail until you [reconnect it](/docs/account-status#reconnect-an-account). A reconnect keeps the `id` and sends `account.connected` with `reconnected: true`. ## account.connected [#accountconnected] `data.object` is the whole account, as `GET /v1/accounts/{id}` returns it, plus `reconnected` to tell a reconnect from a new connection. ```json { "object": { "id": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "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": { "userId": "user_8412" }, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z", "reconnected": false } } ``` `reconnected` is `true` when an account is authorized again, such as after expiry. It is `false` for a new connection, even one after a disconnect. Use `id` as `accounts[].accountId` to publish. [List Accounts](/docs/api-reference/accounts/list-accounts) explains each field. Connecting several accounts at once sends one event each. `metadata` is what you sent when you created the connect session. Use it to find the user the account belongs to, even when the browser never reached your redirect. See [Link Accounts to Your Users](/docs/connection#link-accounts-to-your-users). ## account.disconnected [#accountdisconnected] ```json { "object": { "id": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "handle": "yourbrand", "status": "disconnected", "metadata": { "userId": "user_8412" } } } ``` `handle` is the handle at disconnect time, or an empty string. Store it if you need it, since the API no longer returns the account. `status` is always `disconnected`, and `GET /v1/accounts/{id}` returns `404`. `metadata` is what the account carried, which tells you whose account left. The account no longer keeps it. It fires in these cases. - You disconnect the account in the dashboard or with `DELETE /v1/accounts/{id}`. - The owner removes Onepostly in their Facebook, Instagram or Threads settings, or asks the platform to delete their data. - A new connection cannot be billed. You get `account.connected`, then `account.disconnected`. Connecting it later sends `account.connected` with `reconnected: false`. ## account.expiring [#accountexpiring] `data.object` is the whole account, as `GET /v1/accounts/{id}` returns it. ```json { "object": { "id": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "platform": "linkedin", "displayName": "Your Brand", "handle": "Your Brand", "avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "status": "active", "canAutoRenew": false, "tokenExpiresAt": "2027-04-30T10:00:00.000Z", "profile": "Default", "metadata": {}, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z" } } ``` It fires about 7 days before `tokenExpiresAt`, only when `canAutoRenew` is `false`. An account connected with less time left sends it soon after connecting. It fires once per authorization, and again only after a reconnect. Ask the owner to [reconnect](/docs/account-status#reconnect-an-account) before `tokenExpiresAt`, or the account turns `expired` then and its posts fail. `account.expired` follows on its next use. ## account.expired [#accountexpired] ```json { "object": { "id": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "platform": "linkedin", "handle": "Your Brand", "status": "expired", "reason": "expired", "tokenExpiresAt": "2027-04-30T10:00:00.000Z", "previousStatus": "active" } } ``` ## account.revoked [#accountrevoked] ```json { "object": { "id": "acc_YOUR_TIKTOK_ACCOUNT_ID", "platform": "tiktok", "handle": "yourbrand", "status": "revoked", "reason": "token_invalid", "tokenExpiresAt": "2027-03-16T09:00:00.000Z", "previousStatus": "active" } } ``` ## Expired and Revoked Fields [#expired-and-revoked-fields] | Field | Type | Description | | ---------------- | ---------------------------------- | --------------------------------------------------------------------------- | | `id` | `string` | The account id. | | `platform` | `string` | The account's platform. | | `handle` | `string \| null` | The handle without `@`, or `null`. | | `status` | `"expired" \| "revoked"` | The new status, matching the event. | | `reason` | `string` | Why the account stopped, see below. Handle unknown values. | | `tokenExpiresAt` | `string \| null` | When the last authorization expires, in ISO 8601. `null` without an expiry. | | `previousStatus` | `"active" \| "error" \| "expired"` | The status before. `expired` only on `account.revoked`. | | Event | `reason` | Meaning | | --- | --- | --- | | `account.expired` | `expired` | The authorization reached its expiry | | `account.expired` | `refresh_failed` | The platform declined to extend it | | `account.revoked` | `token_invalid` | The platform rejected it on a request | | `account.revoked` | `refresh_revoked` | It was withdrawn, such as the owner removing the app | Every reason has the same fix. [Reconnect the account](/docs/account-status#reconnect-an-account). Each event fires once per status change, and a `revoked` account never moves back to `expired`. # Comment Webhooks (/docs/webhooks/comments) Confirm your API comments, and react to new Facebook and Instagram comments. Each event carries the comment in `data.object`, as the comment endpoints return it. Each example is the [payload's](/docs/webhooks#payload) `data`. ## Events [#events] | Event | Fires when | Platforms | | --- | --- | --- | | `comment.created` | You comment or reply through the API | Every platform with comments | | `comment.deleted` | You delete a comment, or it is removed on Facebook | Every platform with deletes | | `comment.received` | Anyone comments on a connected account's post | Facebook, Instagram | Listing, hiding, liking and private replies send no event. See [support by platform](/docs/comments#support-by-platform) for the actions each platform offers. ## comment.created [#commentcreated] ```json { "object": { "id": "cmt_xek8zOrjkbzEEKS64mH0wziH8MGiU5FW9ncR4Cx7nx6MRHFFDYsbuEKNov6dlNHDl1U7E06QNOLyEkdfICPfaqaIah3ikn7jpaotvnru2kolc3aecl2LLMOiD", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "platformCommentId": "1900891234567890123", "parentId": "cmt_1L9nrxdhpou1eUhHAMj8Yisi1wMzP69osZE1zdHl3N2cRhHqWmlQOyUKeoJu2SyPVvwjfvSTQRnyZoQcL2SxkRAj2dvuS0kwJEf33vKqWx14qrSsXYivNc4lfC", "text": "Thanks for all the feedback on this launch!", "username": null, "likeCount": 0, "createdAt": "2027-03-15T13:12:40.000Z", "replies": [] } } ``` | Field | Type | Description | | ------------------- | ---------------- | ---------------------------------------------------------------------------- | | `id` | `string` | The comment id, starting with `cmt_`. Use it to reply, delete, hide or like. | | `postId` | `string` | The post the comment is on. | | `accountId` | `string` | The post's account. API comments are posted as this account. | | `platform` | `string` | The account's platform. | | `platformCommentId` | `string` | The comment's id on the platform. | | `parentId` | `string \| null` | The `cmt_` id this replies to. `null` on the post itself. | | `text` | `string` | The comment text as published. | | `username` | `string \| null` | The author's handle. `null` when the platform hides it, as on X. | | `likeCount` | `number \| null` | Likes. `0` or `null` for a new comment. | | `createdAt` | `string \| null` | When it was created, in ISO 8601. | | `replies` | `Comment[]` | Always empty for a new comment. | ## comment.deleted [#commentdeleted] ```json { "object": { "id": "cmt_xek8zOrjkbzEEKS64mH0wziH8MGiU5FW9ncR4Cx7nx6MRHFFDYsbuEKNov6dlNHDl1U7E06QNOLyEkdfICPfaqaIah3ikn7jpaotvnru2kolc3aecl2LLMOiD", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "platformCommentId": "1900891234567890123" } } ``` It carries only the ids and `platform`, which match `comment.created`. On Facebook, it also fires when the author or the Page removes a comment there. It fires only for posts Onepostly knows, such as published or synced ones. A delete through the API sends one event, not two. ## comment.received [#commentreceived] ```json { "object": { "id": "cmt_1favcqJ4EESecYNmroaaaU1lO77s9mVKL017fGpcyOCXzsOinAYE2V5yWPBhZ68L0CYTTX9fr03ZhAwJnw97HmmAVb2FHvTHo07uXsI1FmxybkJDsoXqqTqM7L9XPoZo1VVuWZtGwe", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a04", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "platformCommentId": "122134567890123456_998877665544332", "parentId": null, "text": "Do you ship to Canada?", "username": "Jane Doe", "likeCount": null, "createdAt": "2027-03-15T13:40:12.000Z", "replies": [], "authorId": "7012345678901234" } } ``` The fields match `comment.created`, with these differences. - `postId` is set even for posts made outside Onepostly. - `text` is empty when the platform sends none. - `username` is the Instagram handle or Facebook name, or `null`. - `createdAt` is `null` when the platform sends no time. - `likeCount` is `null`. Read it with [List Comments](/docs/comments#list-comments). - `authorId` is the commenter's platform user id, or `null`. It fires once per comment. [Reply](/docs/comments#reply-to-a-comment) with the event's `id`, or send a [private reply](/docs/comments#send-a-private-reply). To answer keywords without code, use an [automation](/docs/automations). # Engagement Webhooks (/docs/webhooks/engagement) Confirm the likes, bookmarks and reposts your accounts make through the API. Other people's likes and reposts send no event. Each example is the [payload's](/docs/webhooks#payload) `data`. ## Events [#events] | Event | Fires when | | --- | --- | | `engagement.liked` | Your account likes a post | | `engagement.unliked` | Your account removes a like | | `engagement.bookmarked` | Your account bookmarks a post | | `engagement.unbookmarked` | Your account removes a bookmark | | `engagement.reposted` | Your account reposts a post | | `engagement.unreposted` | Your account removes a repost | Every successful `PUT` or `DELETE` on the [engagement routes](/docs/engagement) sends one event, repeats included. See [support by platform](/docs/engagement#support-by-platform). ## Fields [#fields] | Field | Type | Description | | ------------------ | ---------------------------------- | ----------------------------------------------------------------------- | | `action` | `"like" \| "bookmark" \| "repost"` | What the account did. | | `active` | `boolean` | `true` after the action, `false` after it is removed. | | `postId` | `string` | The post's `pst_` id, even when you sent a platform id. Use it to undo. | | `accountId` | `string` | The account that acted. | | `platform` | `string` | The account's platform. | | `platformPostId` | `string` | The post's id on the platform. | | `platformRepostId` | `string \| null` | `engagement.reposted` only. The repost's own platform id, or `null`. | ## Likes and Bookmarks [#likes-and-bookmarks] **engagement.liked** ```json { "object": { "action": "like", "active": true, "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "platformPostId": "1900876543210987654" } } ``` **engagement.unbookmarked** ```json { "object": { "action": "bookmark", "active": false, "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a05", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "platform": "bluesky", "platformPostId": "at://did:plc:4kq7n2xhv3wbzmd5ltc6jy2e/app.bsky.feed.post/3l6oveex3ii2l" } } ``` `engagement.unliked` and `engagement.bookmarked` have the same shape. ## Reposts [#reposts] **engagement.reposted** ```json { "object": { "action": "repost", "active": true, "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a06", "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "platformPostId": "18047285913046723", "platformRepostId": "18047285913099871" } } ``` **engagement.unreposted** ```json { "object": { "action": "repost", "active": false, "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a06", "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "platformPostId": "18047285913046723" } } ``` `engagement.unreposted` has no `platformRepostId`. A quote is a regular post, so it sends [post events](/docs/webhooks/posts) instead. # Inbox Webhooks (/docs/webhooks/inbox) Keep your inbox live for your Facebook Pages and Instagram accounts. Subscribe to these events, with no other setup. Each example is the [payload's](/docs/webhooks#payload) `data`. ## Events [#events] | Event | Fires when | `senderId` | `recipientId` | | --- | --- | --- | --- | | `message.received` | Someone messages your account | The person | Your account | | `message.sent` | Your account sends, here or on the platform | Your account | The person | | `message.delivered` | Your messages reach the person | The person | Your account | | `message.read` | The person reads your messages | The person | Your account | | `message.reaction` | The person adds or removes a reaction | The person | Your account | | `message.postback` | The person taps a button, menu item or ice breaker | The person | Your account | | `message.deleted` | The person unsends a message, Instagram only | The person | Your account | Both ids are platform user ids. Your side is the Page or Instagram account id. The person's side is their page-scoped or Instagram-scoped id. Every event has a `conversationId`. Use it with [Send Message](/docs/api-reference/messages/send-message), [Get Conversation](/docs/api-reference/messages/get-conversation) and [List Messages](/docs/api-reference/messages/list-messages). See [Inbox](/docs/inbox). Bluesky sends no inbox events. ## Common Fields [#common-fields] Every event has these fields in `data.object`. | Field | Type | Description | | ---------------- | --------------------------- | -------------------------------------------------------------------- | | `accountId` | `string` | The connected Page or Instagram account. | | `platform` | `"facebook" \| "instagram"` | The account's platform. | | `conversationId` | `string` | The conversation with the person, the same on every event with them. | | `senderId` | `string` | The sending side's platform user id. | | `recipientId` | `string` | The receiving side's platform user id. | | `sentAt` | `string` | When the message, delivery or read happened, in ISO 8601. | ## message.received [#messagereceived] ```json { "object": { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDUyOTA2MzE4Mjc0OjM0MDI4MjM2Njg0", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "conversationId": "cnv_sd3sE35Ae5QCQzR1AQWlKnfhbDnWJzlN7APMNxzAVnnlApQTAelwzTs2lziEqBjlT0YF4l1kmfGfnjxqELLhb4o5BPK5qNmAAw6MP5LpuDHNpTfiGIhK71qJdPeLh27PU6pQmQWsG0Hcx93oWUmna8cIRJ7TORfCh8PE", "senderId": "6845123987456321", "recipientId": "17841452906318274", "text": "Hi, is the large size back in stock?", "hasAttachments": false, "sentAt": "2027-03-15T14:05:11.000Z" } } ``` - `id` is the message's platform id, as in the inbox endpoints. - `conversationId` is the id [Create Conversation](/docs/api-reference/messages/create-conversation) returns. [List Conversations](/docs/api-reference/messages/list-conversations) may return another `cnv_` id for it, and both work everywhere. - `text` is `null` for an attachment-only message. A [quick reply](/docs/inbox#rich-messages) tap arrives here, with its `title` as `text`. - `hasAttachments` is `true` for an image or other file. Read it with [List Messages](/docs/inbox#read-messages). ## message.sent [#messagesent] ```json { "object": { "id": "m_Xy7Tq2Lk9PzR4vWbN1sA8dE3fG6hJ0cM5uV2iO7yK4lB9nQ1rS6tU3wX8zC5aD2e", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "conversationId": "cnv_8hWTlNv5W91f8vG9PyTrMWblwkWGiiSNXTNABrUoRpfy84mEKvN0dcP5HHKaz568DOcMk", "senderId": "104857392017465", "recipientId": "7012345678901234", "text": "Yes, it ships tomorrow.", "hasAttachments": false, "sentAt": "2027-03-15T14:07:30.000Z" } } ``` The fields match `message.received`, with the sides reversed. `senderId` is your account. `conversationId` is the same. ## message.delivered [#messagedelivered] ```json { "object": { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "conversationId": "cnv_8hWTlNv5W91f8vG9PyTrMWblwkWGiiSNXTNABrUoRpfy84mEKvN0dcP5HHKaz568DOcMk", "senderId": "7012345678901234", "recipientId": "104857392017465", "messageIds": [ "m_Xy7Tq2Lk9PzR4vWbN1sA8dE3fG6hJ0cM5uV2iO7yK4lB9nQ1rS6tU3wX8zC5aD2e" ], "watermark": 1805119651000, "sentAt": "2027-03-15T14:07:31.000Z" } } ``` - `messageIds` lists the delivered messages. When it is empty, use `watermark`. - `watermark` is Unix milliseconds. Everything you sent before it was delivered. It can be `null`. ## message.read [#messageread] ```json { "object": { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "conversationId": "cnv_8hWTlNv5W91f8vG9PyTrMWblwkWGiiSNXTNABrUoRpfy84mEKvN0dcP5HHKaz568DOcMk", "senderId": "7012345678901234", "recipientId": "104857392017465", "watermark": 1805119712000, "sentAt": "2027-03-15T14:08:32.000Z" } } ``` `watermark` is Unix milliseconds. Everything you sent in the conversation before it was read. It can be `null`. A read receipt names no message ids. ## message.reaction [#messagereaction] ```json { "object": { "messageId": "m_Xy7Tq2Lk9PzR4vWbN1sA8dE3fG6hJ0cM5uV2iO7yK4lB9nQ1rS6tU3wX8zC5aD2e", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "conversationId": "cnv_8hWTlNv5W91f8vG9PyTrMWblwkWGiiSNXTNABrUoRpfy84mEKvN0dcP5HHKaz568DOcMk", "senderId": "7012345678901234", "recipientId": "104857392017465", "action": "react", "reaction": "love", "emoji": "❤", "sentAt": "2027-03-15T14:09:02.000Z" } } ``` - `messageId` is the message the person reacted to. - `action` is `react` or `unreact`. - `reaction` names it, such as `love`, and `emoji` shows it. Both can be `null`, mostly on `unreact`. ## message.postback [#messagepostback] ```json { "object": { "messageId": null, "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "conversationId": "cnv_8hWTlNv5W91f8vG9PyTrMWblwkWGiiSNXTNABrUoRpfy84mEKvN0dcP5HHKaz568DOcMk", "senderId": "7012345678901234", "recipientId": "104857392017465", "title": "Order status", "payload": "ORDER_STATUS", "sentAt": "2027-03-15T14:10:44.000Z" } } ``` - `payload` is the value you set on the button, menu item or ice breaker. - `title` is the text the person tapped. - `messageId` is the tap's id on Instagram, `null` on Facebook. You set each `payload` where you create the item. Buttons come from [Rich Messages](/docs/inbox#rich-messages), and the menu and ice breakers come from the [Messenger Profile](/docs/inbox#messenger-profile). ## message.deleted [#messagedeleted] ```json { "object": { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDUyOTA2MzE4Mjc0OjM0MDI4MjM2Njg0", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "conversationId": "cnv_sd3sE35Ae5QCQzR1AQWlKnfhbDnWJzlN7APMNxzAVnnlApQTAelwzTs2lziEqBjlT0YF4l1kmfGfnjxqELLhb4o5BPK5qNmAAw6MP5LpuDHNpTfiGIhK71qJdPeLh27PU6pQmQWsG0Hcx93oWUmna8cIRJ7TORfCh8PE", "senderId": "6845123987456321", "recipientId": "17841452906318274", "sentAt": "2027-03-15T14:12:20.000Z" } } ``` `id` is the unsent message, as in `message.received`. Remove your copy of it. # Webhooks (/docs/webhooks) Register an HTTPS endpoint, and Onepostly sends it a signed `POST` for each subscribed event, such as a published post, a new comment or an account to reconnect. ## Set Up an Endpoint [#set-up-an-endpoint] ### Create the Endpoint [#create-the-endpoint] Create it under **Webhooks** in the dashboard or with the API. Send the URL and `events` from the [Event Catalog](#event-catalog), or `["*"]` for every event, even future ones. **TypeScript** ```typescript import { Configuration, WebhooksApi } from "@onepostly/sdk"; const webhooksApi = new WebhooksApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await webhooksApi.createWebhook({ createWebhookBody: { "name": "Production", "url": "https://example.com/hooks/onepostly", "events": [ "post.published", "post.failed", "account.expired", "account.revoked" ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.webhooks_api import WebhooksApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: webhooks_api = WebhooksApi(api_client) response = await webhooks_api.create_webhook( create_webhook_body={ "name": "Production", "url": "https://example.com/hooks/onepostly", "events": [ "post.published", "post.failed", "account.expired", "account.revoked" ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/webhooks" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Production", "url": "https://example.com/hooks/onepostly", "events": [ "post.published", "post.failed", "account.expired", "account.revoked" ] }' ``` **Response** ```json { "id": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "name": "Production", "url": "https://example.com/hooks/onepostly", "enabled": true, "events": [ "post.published", "post.failed", "account.expired", "account.revoked" ], "createdAt": "2027-03-14T16:20:00.000Z", "updatedAt": "2027-03-14T16:20:00.000Z", "secret": "q3Vt8kRz1mXo5bJw7nLc2yHd9sAf4gPe" } ``` ### Store the Secret [#store-the-secret] Only this `201` and [Rotate the Secret](#rotate-the-secret) return `secret`. Store it right away, because it cannot be read again. To pick your own, send `secret` on create. ### Verify and Acknowledge Each Delivery [#verify-and-acknowledge-each-delivery] [Verify](#verify-signatures) `Onepostly-Signature` against the raw body. Reply with any `2xx` within 10 seconds, and do any slow work after you reply. ### Send a Test Event [#send-a-test-event] Send a `webhook.test` event, whatever the endpoint subscribes to. **TypeScript** ```typescript import { Configuration, WebhooksApi } from "@onepostly/sdk"; const webhooksApi = new WebhooksApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await webhooksApi.testWebhook({ id: "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.webhooks_api import WebhooksApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: webhooks_api = WebhooksApi(api_client) response = await webhooks_api.test_webhook( "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58/test" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "sent": true } ``` `sent: true` means the delivery started. See its result in the [delivery log](#delivery-log). On `sent: false`, send it again. A paused endpoint records the test as failed. The test event's `data` looks like this. ```json { "object": { "message": "Onepostly webhook test event", "webhookId": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" } } ``` ### Endpoint Rules [#endpoint-rules] | Field | Rule | | --- | --- | | `url` | Public HTTPS, no credentials, up to 2,048 characters | | `name` | 1 to 120 characters | | `events` | Event names, or `["*"]` alone | | `secret` | Optional, 16 to 128 characters. Generated if left out | | `enabled` | Optional, default `true`. `false` creates it paused | Every write, even a test, rotation or retry, needs a `read_write` [API key](/docs/authentication#create-an-api-key). ## Manage Endpoints [#manage-endpoints] | Method | Path | Description | | --- | --- | --- | | `GET` | `/v1/webhooks/events` | Lists every event name | | `GET` | `/v1/webhooks` | Lists webhooks, newest first | | `POST` | `/v1/webhooks` | Creates a webhook, with its `secret` | | `GET` | `/v1/webhooks/{id}` | Gets one webhook | | `PATCH` | `/v1/webhooks/{id}` | Changes `name`, `url`, `events` or `enabled` | | `DELETE` | `/v1/webhooks/{id}` | Deletes it and its delivery log | | `POST` | `/v1/webhooks/{id}/rotate-secret` | Replaces the secret | | `POST` | `/v1/webhooks/{id}/test` | Sends a `webhook.test` event | | `GET` | `/v1/webhooks/{id}/deliveries` | Lists its deliveries | | `GET` | `/v1/webhooks/{id}/deliveries/{deliveryId}` | Gets one delivery with its body | | `POST` | `/v1/webhooks/{id}/deliveries/{deliveryId}/retry` | Sends a finished delivery again | `PATCH` changes only the fields you send, and replaces `events` whole. It cannot change the secret. `enabled: false` pauses an endpoint. Events from that time are never sent, and `pending` deliveries end as `failed`. ## Payload [#payload] Every delivery body has these fields. `data.object` is the event's object as it was at that time. A post event carries the whole [post](/docs/post-lifecycle#post-status), as `GET /v1/posts/{id}` returns it. Objects can gain fields, so ignore unknown ones. | Field | Type | Description | | ---------------- | -------- | --------------------------------------------------------------------------------------- | | `id` | `string` | The event id, starting with `evt_`. The same on every retry, so use it to skip repeats. | | `type` | `string` | The event name, such as `post.published`. | | `createdAt` | `string` | When the event happened, in ISO 8601. The same on every retry. | | `organizationId` | `string` | The id of the workspace the event belongs to. | | `data` | `object` | Holds `object`, the object the event is about. | ### Headers [#headers] | Header | Value | | --- | --- | | `Content-Type` | `application/json` | | `User-Agent` | `Onepostly-Webhooks/1.0` | | `Onepostly-Signature` | `t=,v1=` | | `Onepostly-Event` | The event name, same as `type` | | `Onepostly-Event-Id` | The event id, same as `id` | | `Onepostly-Delivery` | The [delivery](#delivery-log) id, the same on every attempt | ### Sample Delivery [#sample-delivery] ```http POST /hooks/onepostly HTTP/1.1 Host: example.com Content-Type: application/json User-Agent: Onepostly-Webhooks/1.0 Onepostly-Signature: t=1805101204,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef Onepostly-Event: post.published Onepostly-Event-Id: evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72 Onepostly-Delivery: dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49 { "id": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72", "type": "post.published", "createdAt": "2027-03-15T09:00:04.412Z", "organizationId": "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b", "data": { "object": { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "published", "text": "New release notes are up.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "1900876543210987654", "url": "https://x.com/i/web/status/1900876543210987654", "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" } } } ``` The real body is compact JSON. Always verify the exact bytes you receive. ## Verify Signatures [#verify-signatures] Each delivery is signed with the endpoint's secret. Before you trust the body, verify the signature in these four steps. Split `Onepostly-Signature` on `,` into `t`, the Unix seconds, and `v1`, the hex signature. Reject it if `t` is more than 300 seconds from your clock. Compute HMAC-SHA256 of `t`, `.` and the raw body, keyed with the UTF-8 secret. Compare your hex digest with `v1` in constant time. ### Timestamp Tolerance [#timestamp-tolerance] The timestamp is signed, so the age check stops replayed deliveries. Each attempt gets a fresh `t`, so real retries pass. Keep your clock synced with NTP. **Node.js** ```ts title="verify-onepostly.ts" import { createHmac, timingSafeEqual } from "node:crypto"; const TOLERANCE_SECONDS = 300; export function verifyOnepostlySignature( secret: string, rawBody: string | Buffer, header: string | null | undefined, ): boolean { if (!header) return false; const parts = new Map( header.split(",").map((part) => { const index = part.indexOf("="); return [part.slice(0, index).trim(), part.slice(index + 1).trim()] as const; }), ); const timestamp = Number(parts.get("t")); const signature = parts.get("v1"); if (!Number.isInteger(timestamp) || !signature) return false; if (Math.abs(Date.now() / 1000 - timestamp) > TOLERANCE_SECONDS) return false; const expected = createHmac("sha256", secret) .update(`${timestamp}.`) .update(rawBody) .digest(); const received = Buffer.from(signature, "hex"); return received.length === expected.length && timingSafeEqual(received, expected); } ``` In Express, use `express.raw`, not `express.json`. With a global `express.json()`, register the webhook route before it. ```ts title="server.ts" import express from "express"; import { verifyOnepostlySignature } from "./verify-onepostly"; const app = express(); app.post( "/hooks/onepostly", express.raw({ type: "application/json" }), (req, res) => { const valid = verifyOnepostlySignature( process.env.ONEPOSTLY_WEBHOOK_SECRET!, req.body, req.get("Onepostly-Signature"), ); if (!valid) { res.status(401).end(); return; } const event = JSON.parse(req.body.toString("utf8")); // Hand `event` to your own background processing, then acknowledge. res.status(200).end(); }, ); ``` In Next.js, read the body with `await req.text()` first. ```ts title="app/hooks/onepostly/route.ts" import { verifyOnepostlySignature } from "@/lib/verify-onepostly"; export async function POST(req: Request) { const rawBody = await req.text(); const valid = verifyOnepostlySignature( process.env.ONEPOSTLY_WEBHOOK_SECRET!, rawBody, req.headers.get("onepostly-signature"), ); if (!valid) { return new Response(null, { status: 401 }); } const event = JSON.parse(rawBody); // Hand `event` to your own background processing, then acknowledge. return new Response(null, { status: 200 }); } ``` **Python** ```python title="verify_onepostly.py" import hashlib import hmac import time TOLERANCE_SECONDS = 300 def verify_onepostly_signature(secret: str, raw_body: bytes, header: str | None) -> bool: if not header: return False try: parts = dict(part.strip().split("=", 1) for part in header.split(",")) timestamp = int(parts["t"]) signature = parts["v1"] except (KeyError, ValueError): return False if abs(time.time() - timestamp) > TOLERANCE_SECONDS: return False signed = f"{timestamp}.".encode() + raw_body expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, signature) ``` In Flask, read `request.get_data()` before `request.json`. ```python title="app.py" import json import os from flask import Flask, request from verify_onepostly import verify_onepostly_signature app = Flask(__name__) @app.post("/hooks/onepostly") def onepostly_webhook(): raw_body = request.get_data() if not verify_onepostly_signature( os.environ["ONEPOSTLY_WEBHOOK_SECRET"], raw_body, request.headers.get("Onepostly-Signature"), ): return "", 401 event = json.loads(raw_body) # Hand `event` to your own background processing, then acknowledge. return "", 200 ``` In FastAPI, read the body with `await request.body()`. ```python title="main.py" import json import os from fastapi import FastAPI, Request, Response from verify_onepostly import verify_onepostly_signature app = FastAPI() @app.post("/hooks/onepostly") async def onepostly_webhook(request: Request) -> Response: raw_body = await request.body() if not verify_onepostly_signature( os.environ["ONEPOSTLY_WEBHOOK_SECRET"], raw_body, request.headers.get("onepostly-signature"), ): return Response(status_code=401) event = json.loads(raw_body) # Hand `event` to your own background processing, then acknowledge. return Response(status_code=200) ``` ### Respond to Failures [#respond-to-failures] | Situation | Respond with | What happens | | --- | --- | --- | | The signature is not valid | `401` | Not retried. The delivery ends as `failed` | | A temporary problem on your side | Any `5xx`, such as `503` | The delivery is retried | | You already processed this `id` | `200` | Nothing. Skip the event | > Never return a `4xx` for a temporary problem. The only `4xx` statuses that are retried are `408` and `429`, so reply with a `5xx` instead. ### Rotate the Secret [#rotate-the-secret] A secret cannot be read again. To replace or recover it, rotate it. The response shows the new `secret` once, so store it right away. **TypeScript** ```typescript import { Configuration, WebhooksApi } from "@onepostly/sdk"; const webhooksApi = new WebhooksApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await webhooksApi.rotateWebhookSecret({ id: "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.webhooks_api import WebhooksApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: webhooks_api = WebhooksApi(api_client) response = await webhooks_api.rotate_webhook_secret( "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58/rotate-secret" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "id": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "name": "Production", "url": "https://example.com/hooks/onepostly", "enabled": true, "events": [ "post.published", "post.failed", "account.expired", "account.revoked" ], "createdAt": "2027-03-14T16:20:00.000Z", "updatedAt": "2027-03-15T12:00:00.000Z", "secret": "Lw4nQ8xTb2Rk7pZc1vHs9mYd3fJe6gAu" } ``` Later attempts use the new secret, so update your handler right away. Deliveries it rejected in between end as `failed`, so [retry them](#retry-a-delivery). ## Delivery and Retries [#delivery-and-retries] | Behavior | Detail | | --- | --- | | Method | `POST` | | Timeout | 10 seconds per attempt | | Success | Any `2xx` | | Retried | `408`, `429`, `5xx`, timeouts and network errors | | Not retried | Any other status. Redirects are not followed | | Attempts | 5, the first included | | Signature | A new `t` each attempt, the same body | | Attempt | Sent | | --- | --- | | 1 | When the event happens | | 2 | 1 minute later | | 3 | 2 minutes later | | 4 | 3 minutes later | | 5 | 4 minutes later | After 5 failed attempts, about 10 minutes in, the delivery ends as `failed`. [Retry it](#retry-a-delivery), or read the current state from the API. | Case | What to do | | --- | --- | | An event arrives twice | Skip an `id` you already handled | | Events arrive out of order | Compare `createdAt`, or read the current state | A failing endpoint never affects publishing or other API calls. ### Delivery Log [#delivery-log] List a webhook's deliveries, newest first. **TypeScript** ```typescript import { Configuration, WebhooksApi } from "@onepostly/sdk"; const webhooksApi = new WebhooksApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await webhooksApi.listWebhookDeliveries({ id: "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", limit: 20, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.webhooks_api import WebhooksApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: webhooks_api = WebhooksApi(api_client) response = await webhooks_api.list_webhook_deliveries( "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", limit=20, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58/deliveries?limit=20" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b03", "webhookId": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "eventId": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a03", "eventType": "account.revoked", "status": "failed", "attempts": 5, "responseStatus": 503, "lastError": "HTTP 503", "createdAt": "2027-03-15T11:00:00.318Z", "deliveredAt": null }, { "id": "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49", "webhookId": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "eventId": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72", "eventType": "post.published", "status": "success", "attempts": 1, "responseStatus": 200, "lastError": null, "createdAt": "2027-03-15T09:00:04.412Z", "deliveredAt": "2027-03-15T09:00:04.987Z" }, { "id": "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b02", "webhookId": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "eventId": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a02", "eventType": "post.failed", "status": "success", "attempts": 2, "responseStatus": 200, "lastError": null, "createdAt": "2027-03-15T09:00:02.205Z", "deliveredAt": "2027-03-15T09:01:02.640Z" } ], "nextCursor": null, "hasMore": false } ``` | Parameter | Effect | | --- | --- | | `status` | `pending`, `success` or `failed`, comma-separated | | `since`, `until` | A [time window](/docs/pagination#time-filters), default the last 7 days | | `q` | The start of an event name or id | | `limit` | 1 to 100, default `50` | | `cursor` | The previous page's `nextCursor` | | Field | Type | Description | | ---------------- | ------------------------------------ | ------------------------------------------------------------------------------------ | | `id` | `string` | The delivery id, starting with `dlv_`. | | `webhookId` | `string` | The webhook the delivery was sent to. | | `eventId` | `string` | The event id, the payload `id`. | | `eventType` | `string` | The event name. | | `status` | `"pending" \| "success" \| "failed"` | `pending` while attempts remain, `success` after a `2xx`, `failed` once it is final. | | `attempts` | `number` | Attempts made so far. | | `responseStatus` | `number \| null` | The last attempt's HTTP status. `null` after a timeout or network error. | | `lastError` | `string \| null` | The last failed attempt's error, such as `HTTP 503`. `null` after a success. | | `createdAt` | `string` | When the delivery was created, in ISO 8601. | | `deliveredAt` | `string \| null` | When it succeeded, in ISO 8601. `null` until then. | `include=facets` adds counts per status, and `include=histogram` adds results over time. Getting one delivery adds `payload`, the exact body sent. ### Retry a Delivery [#retry-a-delivery] Send a finished delivery again. The body and event `id` stay the same, so your duplicate check catches it. The delivery goes back to `pending` with attempts reset. A `pending` one returns `409 DELIVERY_IN_PROGRESS`. **TypeScript** ```typescript import { Configuration, WebhooksApi } from "@onepostly/sdk"; const webhooksApi = new WebhooksApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await webhooksApi.retryWebhookDelivery({ id: "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", deliveryId: "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b03", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.webhooks_api import WebhooksApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: webhooks_api = WebhooksApi(api_client) response = await webhooks_api.retry_webhook_delivery( "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b03", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58/deliveries/dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b03/retry" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "id": "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b03", "webhookId": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "eventId": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a03", "eventType": "account.revoked", "status": "pending", "attempts": 0, "responseStatus": null, "lastError": null, "createdAt": "2027-03-15T11:00:00.318Z", "deliveredAt": null, "payload": { "id": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a03", "type": "account.revoked", "createdAt": "2027-03-15T11:00:00.318Z", "organizationId": "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b", "data": { "object": { "id": "acc_YOUR_TIKTOK_ACCOUNT_ID", "platform": "tiktok", "handle": "yourbrand", "status": "revoked", "reason": "token_invalid", "tokenExpiresAt": "2027-03-16T09:00:00.000Z", "previousStatus": "active" } } } } ``` ## Event Catalog [#event-catalog] Event names are the same on every platform. `data.object.platform` names the platform. Each page shows a sample `data` per event. - [Post Events](/docs/webhooks/posts): Schedules, results, edits, cancels, deletes and outside posts. - [Comment Events](/docs/webhooks/comments): Your API comments, and new Facebook and Instagram comments. - [Inbox Events](/docs/webhooks/inbox): Facebook and Instagram messages, receipts and reactions. - [Review Events](/docs/webhooks/reviews): New recommendations on Facebook Pages. - [Engagement Events](/docs/webhooks/engagement): Likes, bookmarks and reposts made through the API. - [Account Events](/docs/webhooks/accounts): Connects, disconnects, expiry and revoked access. Only [Send a Test Event](#send-a-test-event) sends `webhook.test`. Subscribing does nothing. Every event schema is also in the [API Reference](/docs/api-reference/webhook-events/post-scheduled) and the [OpenAPI spec](https://api.onepostly.com/openapi.json). Use them to generate types for your webhook handler. ## Errors [#errors] | Code | HTTP | Cause | Fix | | --- | --- | --- | --- | | `VALIDATION_ERROR` | 400 | A field breaks the [Endpoint Rules](#endpoint-rules) | Fix the field in `param` | | `FORBIDDEN` | 403 | A `read_only` key tried a write | Use a `read_write` key | | `NOT_FOUND` | 404 | No webhook or delivery has this id | Use a current id | | `DELIVERY_IN_PROGRESS` | 409 | The delivery is still `pending` | Retry once it finishes | Other codes are in [Errors](/docs/error-handling#error-codes). # Post Webhooks (/docs/webhooks/posts) Follow each post from schedule to result, and keep outside posts in sync. Each event is about one account's post, with the whole post in `data.object`. ## Events [#events] | Event | Fires when | | --- | --- | | `post.scheduled` | A post is created with a future `scheduledFor` | | `post.published` | A post is live | | `post.failed` | A post failed to publish | | `post.cancelled` | You deleted a post before it published | | `post.deleted` | You deleted a live post, or an outside post is gone | | `post.updated` | You edited a scheduled post, a platform id arrived, or an outside post changed | | `post.created` | A new outside post was found | ## Event Order [#event-order] A scheduled post sends `post.scheduled` on create, then `post.published` or `post.failed`. A post that publishes now skips `post.scheduled`. Each post of a request finishes on its own, so one can fail while another publishes. Match them up by their shared `groupId`. Deliveries can arrive out of order, so compare `updatedAt`, or call `GET /v1/posts/{id}` for the current state. See [Post Status](/docs/post-lifecycle#post-status). ## Payloads [#payloads] Each example is the `data` of the [webhook payload](/docs/webhooks#payload). ### post.published [#postpublished] ```json { "object": { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "published", "text": "New release notes are up.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "1900876543210987654", "url": "https://x.com/i/web/status/1900876543210987654", "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" } } ``` `platformPostId` and `url` identify the post on the platform. `publishedAt` is when it went live. On TikTok and Facebook, the id and URL can change. On TikTok, the event can come before the post is public. Then `platformPostId` is a publish id starting with `v_pub_` or `p_pub_`. `url` is the profile URL for videos, or `null` for photos. A later `post.updated` brings the public id and URL, but only if the post goes public. On Facebook, a video or Reel first has its video id as `platformPostId`. A `post.updated` soon brings the Page post id and `url`. Update the values you stored when these arrive. ### post.failed [#postfailed] The post has `status: "failed"` and the reason in `error`. ```json { "object": { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "failed", "text": "New release notes are up.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/spring.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": null, "url": null, "error": { "code": "TOKEN_INVALID", "message": "Connection token was revoked. Reconnect the account to continue publishing." }, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:02.000Z" } } ``` Branch on `error.code`, listed in [Error Codes](/docs/error-handling#error-codes). `error.message` is for logs and your UI, and its wording can change, so never match on it. `TOKEN_INVALID` means the account needs a reconnect. [`account.expired` and `account.revoked`](/docs/webhooks/accounts) tell you once per account, not once per post. If a thread failed part way, `platformPostId` points to the part that went live. To remove that part, [delete the post](/docs/post-lifecycle#delete-a-post). ### post.scheduled, post.cancelled, post.deleted [#postscheduled-postcancelled-postdeleted] These carry the post after the change, with `status` `scheduled`, `cancelled` or `deleted`. `scheduledFor` is local time in `timezone`. `post.deleted` fires once the platform confirms it, for a thread once every part is gone. ### post.updated [#postupdated] This carries the post after the change. An edit keeps it `scheduled` with the new content. If it shared a `groupId`, it gets its own. ## Posts Made Outside Onepostly [#posts-made-outside-onepostly] `post.created`, `post.updated` and `post.deleted` also report posts made on the platform itself, with `source: "external"`. On Facebook, they fire on their own, usually within a minute. Elsewhere they fire when [`POST /v1/accounts/{id}/sync`](/docs/publishing#posts-made-outside-onepostly) finds a change. See [Posts Made Outside Onepostly](/docs/publishing#posts-made-outside-onepostly). | Event | Fires when | | --- | --- | | `post.created` | A new post is found. A first sync reports recent posts, so upsert by `id` | | `post.updated` | `url`, `mediaKind` or `publishedAt` changed, or a deleted post is back | | `post.deleted` | The post is gone, with `status` `deleted` | ```json { "object": { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a03", "groupId": null, "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "external", "status": "published", "text": null, "mediaKind": "image", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "1901234567890123456", "url": "https://x.com/yourbrand/status/1901234567890123456", "error": null, "publishedAt": "2027-03-16T14:22:05.000Z", "metrics": null, "createdAt": "2027-03-16T15:03:47.120Z", "updatedAt": "2027-03-16T15:03:47.120Z" } } ``` Outside posts have no `groupId` or `text`, but their `id` works with analytics, comments and engagement like any other post. # Review Webhooks (/docs/webhooks/reviews) Answer new reviews while they are fresh. Subscribe to `review.received`, with no other setup. The example is the [payload's](/docs/webhooks#payload) `data`. ## Events [#events] | Event | Fires when | Platforms | | --- | --- | --- | | `review.received` | Someone recommends a Page, or does not | Facebook | ## review.received [#reviewreceived] ```json { "object": { "id": "1029384756473829", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "recommendation": "positive", "rating": null, "text": "Fast delivery and friendly support.", "reviewerName": "Jane Doe", "createdAt": "2027-03-15T16:02:41.000Z" } } ``` | Field | Type | Description | | ---------------- | ---------------------------------- | ---------------------------------------------------------------------------- | | `id` | `string` | The review's Facebook id, as in List Page Reviews. | | `accountId` | `string` | The connected Facebook Page. | | `platform` | `"facebook"` | The account's platform. | | `recommendation` | `"positive" \| "negative" \| null` | Whether the reviewer recommends the Page. `null` on older star-only reviews. | | `rating` | `number \| null` | The legacy 1 to 5 stars. `null` without stars. | | `text` | `string \| null` | The review text, or `null`. | | `reviewerName` | `string \| null` | The reviewer's name, or `null` when Facebook hides it. | | `createdAt` | `string \| null` | When it was written, in ISO 8601. | It fires once per review. For reviews written before you subscribed, [List Page Reviews](/docs/api-reference/facebook/list-account-reviews) reads every review, newest first. See [Facebook](/docs/facebook). # Bluesky (/docs/bluesky) Publish posts and threads, engage, send messages and read metrics. ## Quick Reference [#quick-reference] | Property | Value | | ------------------ | --------------------------------------- | | Account types | Bluesky accounts | | Connection method | Handle and App Password | | Post types | `text`, `image`, `multi_image`, `video` | | Max media per post | 4 | | Text limit | 300 characters (graphemes) | | Threads | Yes | | Quotes | Yes | | Remote delete | Yes (Whole thread) | | Comments | Yes | | Likes | Yes | | Reposts | Yes | | Bookmarks | Yes | | Direct messages | Yes (Text only) | | Post analytics | Yes | | Account analytics | Yes (Stats) | Bluesky counts graphemes, so a multi-part emoji counts once. ## Connect [#connect] Bluesky connects with a handle and an App Password, with no sign-in flow. Create one in Bluesky under **Settings → Privacy and Security → App Passwords**. For the [inbox](#inbox), turn on **Allow access to your direct messages** there. Connect in **Dashboard → Connections**, or send both to [Connect a Bluesky Account](/docs/api-reference/accounts/create-account). **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.createAccount({ createAccountBody: { "platform": "bluesky", "identifier": "alice.bsky.social", "appPassword": "abcd-efgh-ijkl-mnop", "profile": "Default" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.create_account( create_account_body={ "platform": "bluesky", "identifier": "alice.bsky.social", "appPassword": "abcd-efgh-ijkl-mnop", "profile": "Default" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "platform": "bluesky", "identifier": "alice.bsky.social", "appPassword": "abcd-efgh-ijkl-mnop", "profile": "Default" }' ``` **Response** ```json { "id": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "bluesky", "displayName": "Alice", "handle": "alice.bsky.social", "avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "status": "active", "canAutoRenew": true, "tokenExpiresAt": "2027-03-01T12:00:00.000Z", "profile": "Default", "metadata": {}, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z" } ``` `identifier` is the handle, a custom-domain handle or the account email. `profile` files the account, creating it if needed. Without it, it goes to Default. A wrong handle or password returns `422 AUTH_FAILED`. ### Permissions [#permissions] Bluesky has no OAuth scopes. The App Password decides what works. | App Password | Used for | | --- | --- | | Any | Posts, replies, likes, reposts, bookmarks and analytics | | With message access | The inbox | ### Staying Connected [#staying-connected] The connection renews itself, so `canAutoRenew` is `true`. Revoking the App Password ends it. You then get `TOKEN_INVALID`. [Reconnect](/docs/account-status#bluesky) with a new App Password and the same account. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.reconnectAccount({ id: "acc_YOUR_BLUESKY_ACCOUNT_ID", reconnectAccountBody: { "identifier": "alice.bsky.social", "appPassword": "qrst-uvwx-yzab-cdef" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.reconnect_account( "acc_YOUR_BLUESKY_ACCOUNT_ID", reconnect_account_body={ "identifier": "alice.bsky.social", "appPassword": "qrst-uvwx-yzab-cdef" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts/acc_YOUR_BLUESKY_ACCOUNT_ID/reconnect" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "identifier": "alice.bsky.social", "appPassword": "qrst-uvwx-yzab-cdef" }' ``` **Response** ```json { "type": "account", "account": { "id": "acc_YOUR_BLUESKY_ACCOUNT_ID", "platform": "bluesky", "displayName": "Alice", "handle": "alice.bsky.social", "avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "status": "active", "canAutoRenew": true, "tokenExpiresAt": "2027-03-15T12:00:00.000Z", "profile": "Default", "metadata": {}, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } } ``` A different Bluesky account returns `RECONNECT_MISMATCH`. A missing App Password returns `BLUESKY_RECONNECT_APP_PASSWORD`. Reconnect the same way to add message access later. ## Publish [#publish] **TypeScript** ```typescript 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": "How to handle time zones in scheduled posts.", "accounts": [ { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "bluesky": { "link": "https://onepostly.com/blog/time-zones" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "How to handle time zones in scheduled posts.", "accounts": [ { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "bluesky": { "link": "https://onepostly.com/blog/time-zones" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "How to handle time zones in scheduled posts.", "accounts": [ { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "bluesky": { "link": "https://onepostly.com/blog/time-zones" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "platform": "bluesky", "source": "onepostly", "status": "publishing", "text": "How to handle time zones in scheduled posts.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": { "bluesky": { "link": "https://onepostly.com/blog/time-zones" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` Once live, `platformPostId` is the `at://` URI and `url` its `bsky.app` link. ### Post Types [#post-types] | `mediaKind` | Publishes | Media | | --- | --- | --- | | `text` | Text post | None, `text` required | | `image` | Image post | 1 image | | `multi_image` | Image gallery | 2 to 4 images | | `video` | Video post | 1 video | Text goes up to 300 graphemes. `stories` returns `400 VALIDATION_ERROR`. #### Rich Text [#rich-text] Mentions, hashtags and links in the text become links, with no markup. | You write | It becomes | | --- | --- | | `@alice.bsky.social` | A mention, if the handle exists | | `#launch` | A hashtag | | `https://...` | A link, with a card only from [`link`](#link-card) | This works in posts, `thread` replies and comment replies. ### Threads [#threads] Add `thread` for 1 to 25 replies, each under the one before. The top-level `text` and `media` are the first post. See [Threads, Replies and Quotes](/docs/replies-and-quotes). | Rule | Detail | | --- | --- | | Reply text | Up to 300, empty only with media | | Reply media | 1 to 4 images, or 1 video | | Options | `link` and `quotePostId` on the first post. `langs` on all | | Checked first | All text and media, before anything goes live | | Accounts | All on X, Threads or Bluesky | **TypeScript** ```typescript 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": "How we cut our build time in half.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/build-chart.png" } ], "thread": [ { "text": "1/ We cached dependencies between runs." }, { "text": "2/ Then we split tests across 4 machines.", "media": [ { "url": "https://cdn.onepostly.com/media/split-1.png" }, { "url": "https://cdn.onepostly.com/media/split-2.png" } ] } ], "accounts": [ { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "How we cut our build time in half.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/build-chart.png" } ], "thread": [ { "text": "1/ We cached dependencies between runs." }, { "text": "2/ Then we split tests across 4 machines.", "media": [ { "url": "https://cdn.onepostly.com/media/split-1.png" }, { "url": "https://cdn.onepostly.com/media/split-2.png" } ] } ], "accounts": [ { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "How we cut our build time in half.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/build-chart.png" } ], "thread": [ { "text": "1/ We cached dependencies between runs." }, { "text": "2/ Then we split tests across 4 machines.", "media": [ { "url": "https://cdn.onepostly.com/media/split-1.png" }, { "url": "https://cdn.onepostly.com/media/split-2.png" } ] } ], "accounts": [ { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "platform": "bluesky", "source": "onepostly", "status": "publishing", "text": "How we cut our build time in half.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/build-chart.png" } ], "thread": [ { "text": "1/ We cached dependencies between runs.", "media": [] }, { "text": "2/ Then we split tests across 4 machines.", "media": [ { "url": "https://cdn.onepostly.com/media/split-1.png" }, { "url": "https://cdn.onepostly.com/media/split-2.png" } ] } ], "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" } ] } ``` `platformPostId` and `url` point to the first post. If a reply fails, earlier posts stay live and the post ends `failed`. ### Replies and Quotes [#replies-and-quotes] `bluesky.replyToPostId` replies to a post, and `bluesky.quotePostId` quotes one. Both take your `pst_` id or any `at://` URI. A quote can carry media or a link card. **TypeScript** ```typescript 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": "Worth reading before your next launch.", "accounts": [ { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "bluesky": { "quotePostId": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Worth reading before your next launch.", "accounts": [ { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "bluesky": { "quotePostId": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Worth reading before your next launch.", "accounts": [ { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "bluesky": { "quotePostId": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "platform": "bluesky", "source": "onepostly", "status": "publishing", "text": "Worth reading before your next launch.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": { "bluesky": { "quotePostId": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` A `pst_` id not live yet returns `409 POST_NOT_PUBLISHED`. An `at://` URI Bluesky cannot find fails with `INVALID_REPLY` or `INVALID_QUOTE`. These replies send post webhooks. [Comment](#comments) replies send `comment.created`. ### Options [#options] Options go under `bluesky`. Thread replies go in the top-level `thread`. | Field | Type | Description | | ----------------------- | ---------- | ------------------------------------------------ | | `accountId` (required) | `string` | The Bluesky account id. | | `text` | `string` | This account's text, up to 300 graphemes. | | `bluesky.replyToPostId` | `string` | The post to reply to, as a pst_ id or at:// URI. | | `bluesky.quotePostId` | `string` | The post to quote, as a pst_ id or at:// URI. | | `bluesky.link` | `string` | A link card on the first post. Text posts only. | | `bluesky.langs` | `string[]` | Up to 3 language tags, such as ["en"]. | #### Link Card [#link-card] `link` adds a card for a URL, titled with the URL, with no image. A post holds one embed, so `link` with media returns `400 VALIDATION_ERROR`. #### Post Languages [#post-languages] `langs` takes up to 3 BCP-47 tags, such as `["pt", "en-US"]`, for feed filters. They cover the first post and every `thread` reply. Set a default with [Update Account Settings](/docs/api-reference/bluesky/update-account-settings). A post's own `langs` wins. ### Media Requirements [#media-requirements] These are Bluesky's limits, on top of the [Media URL Requirements](/docs/media-uploads#media-url-requirements). | Property | Images | Video | | --- | --- | --- | | Max size | 2 MB each | 100 MB | | Per post | 1, or 2 to 4 | 1 | | Per thread reply | 1 to 4 | 1, alone | Images are posted without alt text. ### Scheduling, Editing and Deleting [#scheduling-editing-and-deleting] [Scheduling and editing](/docs/scheduling) work as usual. Published posts cannot be edited. [Deleting](/docs/post-lifecycle#delete-a-post) removes the whole thread, replies first, even a partial one. A partial delete returns `THREAD_DELETE_PARTIAL`, so send it again. Posts made outside Onepostly cannot be deleted and return `409 NOT_DELETABLE`. Past Bluesky's hourly and daily record caps, you get `QUOTA_EXCEEDED`. ## Engagement [#engagement] See [Comments](/docs/comments) and [Likes and Reposts](/docs/engagement) for the requests. | Action | Supported | Notes | | --- | --- | --- | | List comments | Yes | Nested replies, with `parentId` | | Comment or reply | Yes | Up to 300 graphemes | | Delete a comment | Yes | Only the account's own replies | | Like, repost, bookmark | Yes | Any post. Repeats keep one | | Undo a repost | Yes | Even reposts made outside | | List reposters | Yes | Paginated with `cursor` | | Quote | Yes | See [Replies and Quotes](#replies-and-quotes) | | Hide or like a comment | No | `UNSUPPORTED_PLATFORM` | | Private reply | No | `UNSUPPORTED_PLATFORM` | Name a post by its `pst_` id or `at://` URI, percent-encoded in the path. **TypeScript** ```typescript import { Configuration, EngagementApi } from "@onepostly/sdk"; const engagementApi = new EngagementApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await engagementApi.likePost({ id: "acc_YOUR_BLUESKY_ACCOUNT_ID", postId: "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.engagement_api import EngagementApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: engagement_api = EngagementApi(api_client) response = await engagement_api.like_post( "acc_YOUR_BLUESKY_ACCOUNT_ID", "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X PUT "https://api.onepostly.com/v1/accounts/acc_YOUR_BLUESKY_ACCOUNT_ID/likes/at%3A%2F%2Fdid%3Aplc%3Az72i7hdynmk6r22z27h6tvur%2Fapp.bsky.feed.post%2F3l6oveex3ii2l" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "platform": "bluesky", "liked": true } ``` `platformRepostId` is always `null`. Undo a repost with the same post. ### Comments [#comments] On Bluesky, comments are replies. `platformCommentId` is the `at://` URI. The list includes nested replies. `hasMore` is always `false`, so raise `limit`. ## Inbox [#inbox] Bluesky messages are text only, up to 1,000 graphemes. See [Inbox](/docs/inbox). | Action | Supported | Notes | | --- | --- | --- | | List and read | Yes | Paginated with `cursor` | | Start a conversation | Yes | By handle or DID | | Send text | Yes | Up to 1,000 graphemes | | Rich messages | No | Text only | | Message webhooks | No | List conversations instead | **TypeScript** ```typescript import { Configuration, InboxApi } from "@onepostly/sdk"; const inboxApi = new InboxApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await inboxApi.createConversation({ id: "acc_YOUR_BLUESKY_ACCOUNT_ID", createConversationBody: { "recipient": "alice.bsky.social" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.inbox_api import InboxApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: inbox_api = InboxApi(api_client) response = await inbox_api.create_conversation( "acc_YOUR_BLUESKY_ACCOUNT_ID", create_conversation_body={ "recipient": "alice.bsky.social" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts/acc_YOUR_BLUESKY_ACCOUNT_ID/conversations" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "recipient": "alice.bsky.social" }' ``` **Response** ```json { "id": "cnv_N8DDJ7ieEJmIzAr2wushOgeM1glQf4eApHsgJ7wvMnpr40JrsnbsLrjrYGUdWsKiiASmzv", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "members": [ { "id": "did:plc:k4m2v7xq3nzr5yhtw6bpa2ce", "username": "yourbrand.bsky.social", "displayName": "Your Brand" }, { "id": "did:plc:t6xq2b4n7rk3vzm5wy2hpecj", "username": "alice.bsky.social", "displayName": "Alice" } ], "muted": false, "unreadCount": 1, "lastMessage": { "id": "3lkqa2c5rtv2m", "text": "Hi! Is the beta open yet?", "sentAt": "2027-03-15T09:30:00.000Z" } } ``` An existing conversation comes back as is. Member ids and `senderId` are DIDs. `muted` is real on Bluesky. A deleted message has `text: null`. Follow-only settings or a block return `RECIPIENT_UNREACHABLE`. ## Analytics [#analytics] ### Metrics [#metrics] | Field | Bluesky metric | | --- | --- | | `impressions`, `reach`, `views` | Always `null` | | `likes` | `likeCount` | | `comments` | `replyCount` | | `shares` | `repostCount` + `quoteCount` | | `saves` | `bookmarkCount` | | `engagement` | `likes` + `comments` + `shares` + `saves` | Bluesky does not report impressions, reach or views. Freshness is the [standard](/docs/analytics#freshness). ### Analytics Status [#analytics-status] A fresh post can read `pending` until its first reading arrives. A deleted post reads `unavailable` with the code `POST_NOT_FOUND`. ### Account Stats [#account-stats] [Get Account Stats](/docs/api-reference/accounts/get-account-stats) returns live counts. `videoCount` is all posts. `likesCount` is always `null`. There are no account insights. [List Account Media](/docs/api-reference/accounts/list-account-media) lists posts with media, including reposts. ## Limitations [#limitations] Not available for Bluesky through Onepostly. - Editing a published post - Alt text - Custom link card titles or images - Lists, feeds, pins and content labels - Choosing who can reply - Hiding or liking replies - Files in messages - Webhooks for messages or others' replies - Impressions, reach and views - Account insights - Stories ## Errors [#errors] Breaking a rule here returns `400 VALIDATION_ERROR` and creates nothing. Every code is in [Errors](/docs/error-handling). ### Connect Errors [#connect-errors] | Code | Cause | Fix | | --- | --- | --- | | `AUTH_FAILED` | `422`. Wrong handle or App Password | Check both, or make a new password | | `RECONNECT_MISMATCH` | Another Bluesky account | Use the original handle | | `BLUESKY_RECONNECT_APP_PASSWORD` | No `identifier` or `appPassword` | Send both | ### Publish Errors [#publish-errors] | Code | Cause | Fix | | --- | --- | --- | | `INVALID_MULTI_IMAGE` | Over 4 images | Send 2 to 4 | | `INVALID_MEDIA` | Too large, empty, or video with other files | See [Media Requirements](#media-requirements) | | `INVALID_REPLY`, `INVALID_QUOTE` | Not an `at://` URI, or not found | Use an existing post's URI | | `QUOTA_EXCEEDED` | Bluesky's record limit | Try after the time in the message | | `ACCOUNT_SUSPENDED` | Suspended or taken down | Restore it in Bluesky | | `THREAD_DELETE_PARTIAL` | Some replies were not deleted | Send the delete again | ### Engagement and Inbox Errors [#engagement-and-inbox-errors] | Code | Cause | Fix | | --- | --- | --- | | `POST_ACCOUNT_MISMATCH` | Another account's `pst_` id | Use the `at://` URI | | `INVALID_EXTERNAL_ID` | Not an `at://` URI | Send the encoded URI | | `RESOLVE_FAILED` | The post or parent is gone | Check it exists | | `ATTACHMENT_UNSUPPORTED` | An attachment on Bluesky | Put a link in the text | | `TEMPLATE_UNSUPPORTED` | Buttons or cards on Bluesky | Send plain text | | `RECIPIENT_UNREACHABLE` | Not accepting your messages | Reply to their post instead | | `CONVO_LOCKED` | The conversation is locked | Reach them another way | | `INBOX_PERMISSION` | No message access | Reconnect with message access | # Facebook (/docs/facebook) Publish to a Page, answer comments and Messenger, and read Page analytics. ## Quick Reference [#quick-reference] | Property | Value | | ------------------ | ---------------------------------------------------------- | | Account types | Facebook Pages | | Connection method | OAuth, one account per Page | | Post types | `text`, `image`, `multi_image`, `video`, `reel`, `stories` | | Max media per post | 10 | | Text limit | 63,206 characters, title 100 (Reels) | | Threads | No | | Quotes | No | | Remote delete | Yes | | Comments | Yes | | Likes | Yes | | Reposts | No | | Bookmarks | No | | Direct messages | Yes (Messenger) | | Post analytics | Yes | | Account analytics | Yes (Stats and insights) | Each account is one Page. Profiles and Groups cannot connect. Posts made on the Page show up on their own, usually within a minute. Older ones need a [sync](/docs/publishing#posts-made-outside-onepostly). ## Connect [#connect] Connect a Page in **Dashboard → Connections**, or with a [connect session](/docs/connection). Each Page is its own account. Your Facebook role on the Page sets what works. | Feature | Page access needed | | --- | --- | | Publishing | Content | | Inbox | Messages | | Analytics | Insights | Facebook shows a Page picker during connect. To show your own picker instead, add `headless: true`. See [Pick a Page](/docs/connection#pick-a-page-or-account) for the steps. ### Permissions [#permissions] | Scope | Used for | | --- | --- | | `pages_show_list`, `business_management` | Listing your Pages | | `pages_manage_posts` | Publishing and deleting | | `pages_read_engagement` | Reading posts and counts | | `pages_read_user_content` | Comments and recommendations | | `pages_manage_engagement` | Commenting, hiding and liking | | `read_insights` | Analytics | | `pages_messaging` | Messenger and private replies | | `pages_manage_metadata` | Webhooks for comments, messages and posts | | `public_profile` | Facebook sign-in | ### Staying Connected [#staying-connected] Access renews itself, so `canAutoRenew` is `true`. Access ends on a password change, an app removal or a lost Page role. Then [reconnect](/docs/account-status#reconnect-an-account). The id stays the same. Do the same on a `*_PERMISSION` code. ## Publish [#publish] **TypeScript** ```typescript 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": "Our spring menu is live.", "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "link": "https://example.com/spring-menu" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Our spring menu is live.", "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "link": "https://example.com/spring-menu" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Our spring menu is live.", "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "link": "https://example.com/spring-menu" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "source": "onepostly", "status": "publishing", "text": "Our spring menu is live.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": { "facebook": { "link": "https://example.com/spring-menu" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` Once published, `url` links to the post. Stories have no `url`. ### Post Types [#post-types] | `mediaKind` | Publishes | Media | | --- | --- | --- | | `text` | Feed post | None, `text` or `link` required | | `image` | Photo post | 1 image | | `multi_image` | Album or link carousel | 2 to 10 images | | `video` | Feed video | 1 video | | `reel` | Reel | 1 vertical video | | `stories` | Story, for 24 hours | 1 image or video | - One video without `mediaKind` is a feed `video`. Set `reel` or `stories`. - Text goes up to 63,206 characters. Stories show no text. - An album with a video fails with `INVALID_MEDIA`. A feed video is `published` once Facebook accepts it. Its `platformPostId` and `url` later switch to the post, with a `post.updated`. #### Reel [#reel] `facebook.reelTitle` adds a title, apart from the caption. **TypeScript** ```typescript 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": "Behind the counter on a Saturday morning.", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/saturday.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "reelTitle": "Saturday rush" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Behind the counter on a Saturday morning.", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/saturday.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "reelTitle": "Saturday rush" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Behind the counter on a Saturday morning.", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/saturday.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "reelTitle": "Saturday rush" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "source": "onepostly", "status": "publishing", "text": "Behind the counter on a Saturday morning.", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/saturday.mp4" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "facebook": { "reelTitle": "Saturday rush" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` A Story takes no options, not even `firstComment` or `geoRestriction`. Sending either one on a Story returns `400`. ### Options [#options] Options go under `facebook`. On the wrong media kind, they return `400`. The exceptions are `carouselCards`, `carouselLink` and `textFormatPresetId`, which are checked when the post publishes. | Field | Type | Description | | ----------------------------- | --------------------------------------------------------- | --------------------------------------------------------------------- | | `accountId` (required) | `string` | The Facebook account id. | | `text` | `string` | This Page's text, up to 63,206 characters. | | `facebook.link` | `string` | A link preview. Text posts only. | | `facebook.firstComment` | `string` | A Page comment after publish, up to 8,000 characters. Not on Stories. | | `facebook.reelTitle` | `string` | The Reel title, up to 100 characters. | | `facebook.carouselCards` | `{ link: string; name?: string; description?: string }[]` | One link card per image. See Link Carousel. | | `facebook.carouselLink` | `string` | The carousel's end card link. | | `facebook.textFormatPresetId` | `string` | A colored text background preset. Text posts only. | | `facebook.geoRestriction` | `string[]` | 1 to 25 country codes. Only text and multi_image. | If Facebook refuses `firstComment`, the post still publishes. #### Link Carousel [#link-carousel] `carouselCards` gives each image of a `multi_image` post its own link. Send one card per image, in `media` order. Each card's `name` and `description` can be up to 255 characters long. **TypeScript** ```typescript 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": "New arrivals this week.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/chair.jpg" }, { "url": "https://cdn.onepostly.com/media/lamp.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "carouselLink": "https://example.com/new", "carouselCards": [ { "link": "https://example.com/new/chair", "name": "Oak chair", "description": "Solid oak, hand finished" }, { "link": "https://example.com/new/lamp", "name": "Brass lamp" } ] } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "New arrivals this week.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/chair.jpg" }, { "url": "https://cdn.onepostly.com/media/lamp.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "carouselLink": "https://example.com/new", "carouselCards": [ { "link": "https://example.com/new/chair", "name": "Oak chair", "description": "Solid oak, hand finished" }, { "link": "https://example.com/new/lamp", "name": "Brass lamp" } ] } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "New arrivals this week.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/chair.jpg" }, { "url": "https://cdn.onepostly.com/media/lamp.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "carouselLink": "https://example.com/new", "carouselCards": [ { "link": "https://example.com/new/chair", "name": "Oak chair", "description": "Solid oak, hand finished" }, { "link": "https://example.com/new/lamp", "name": "Brass lamp" } ] } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "source": "onepostly", "status": "publishing", "text": "New arrivals this week.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/chair.jpg" }, { "url": "https://cdn.onepostly.com/media/lamp.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "facebook": { "carouselLink": "https://example.com/new", "carouselCards": [ { "link": "https://example.com/new/chair", "name": "Oak chair", "description": "Solid oak, hand finished" }, { "link": "https://example.com/new/lamp", "name": "Brass lamp" } ] } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` A wrong media kind or card count fails with `INVALID_CAROUSEL`. Without cards, `carouselLink` is ignored and the post is a plain album. #### Text Background [#text-background] `textFormatPresetId` shows a text post as large text on a color. On other kinds, the post fails with `TEXT_FORMAT_UNSUPPORTED`. #### Geo Restriction [#geo-restriction] `geoRestriction` shows the post only in the listed countries. It works on `text` and `multi_image`. Other kinds return `400`. **TypeScript** ```typescript 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": "Free shipping this week in the US and Canada.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/ship-1.jpg" }, { "url": "https://cdn.onepostly.com/media/ship-2.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "geoRestriction": [ "US", "CA" ] } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Free shipping this week in the US and Canada.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/ship-1.jpg" }, { "url": "https://cdn.onepostly.com/media/ship-2.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "geoRestriction": [ "US", "CA" ] } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Free shipping this week in the US and Canada.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/ship-1.jpg" }, { "url": "https://cdn.onepostly.com/media/ship-2.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "facebook": { "geoRestriction": [ "US", "CA" ] } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "source": "onepostly", "status": "publishing", "text": "Free shipping this week in the US and Canada.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/ship-1.jpg" }, { "url": "https://cdn.onepostly.com/media/ship-2.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "facebook": { "geoRestriction": [ "US", "CA" ] } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` ### Media Requirements [#media-requirements] These are Facebook's limits, on top of the [Media URL Requirements](/docs/media-uploads#media-url-requirements). #### Images [#images] | Property | Requirement | | --- | --- | | Formats | JPEG, PNG, GIF, BMP, TIFF | | Max size | 4 MB | | Per post | 1, or 2 to 10 on `multi_image` | #### Videos [#videos] | Property | Feed video | Reel | Story | | --- | --- | --- | --- | | Formats | MP4, MOV | MP4, MOV | MP4 | | Max size | Facebook's limit | 4 GB | 100 MB | | Duration | Facebook's limit | 3 to 90 s | 3 to 60 s | | Aspect ratio | Any | 9:16 | 9:16 | | Resolution | Any | 1080 × 1920, min 540 × 960 | Same | | Frame rate | Any | 24 to 60 fps | 24 to 60 fps | A URL ending in `.mp4`, `.mov`, `.m4v`, `.webm` or `.avi` is a video. ### Scheduling, Editing and Deleting [#scheduling-editing-and-deleting] [Scheduling and editing](/docs/scheduling) work as usual. Published posts cannot be edited. [Deleting](/docs/post-lifecycle#delete-a-post) removes a post from the Page. A post already gone counts as deleted. Posts made on Facebook return `409 NOT_DELETABLE`. Delete them on Facebook. ## Engagement [#engagement] Act as the Page. See [Comments](/docs/comments) and [Likes and Reposts](/docs/engagement). | Action | Supported | Notes | | --- | --- | --- | | Like or unlike a post | Yes | Repeats succeed | | List comments | Yes | Up to 25 replies each. Not on Stories | | Comment or reply | Yes | Up to 8,000 characters | | Delete a comment | Yes | When Facebook allows it | | Hide or unhide | Yes | The author and friends still see it | | Like a comment | Yes | Repeats succeed | | Private reply | Yes | One per comment, 7 days, 2,000 characters | | Repost, quote, bookmark | No | `UNSUPPORTED_PLATFORM` | Like a post by its `pst_` id or Facebook id. Another Page's `pst_` id fails. `username` on a comment is the commenter's name, or `null`. A comment removed on Facebook sends a [`comment.deleted`](/docs/webhooks/comments) webhook. ## Inbox [#inbox] The Page's Messenger inbox. See [Inbox](/docs/inbox) for the requests. | Action | Supported | Notes | | --- | --- | --- | | List and read | Yes | `muted` is always `false` | | Start a conversation | Yes | By Page-scoped id (PSID) | | Send text | Yes | Up to 2,000 characters, within 24 hours | | [Rich messages](/docs/inbox#rich-messages) | Yes | Attachments, quick replies, buttons, cards | | Ice breakers and menu | Yes | See [Messenger Setup](#messenger-setup) | | [Automations](/docs/automations) | Yes | Up to 20 rules per Page | | Message tags | No | No sends after 24 hours | Facebook has no username lookup. Find a PSID in `members` or a `senderId`. **TypeScript** ```typescript import { Configuration, InboxApi } from "@onepostly/sdk"; const inboxApi = new InboxApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await inboxApi.createConversation({ id: "acc_YOUR_FACEBOOK_ACCOUNT_ID", createConversationBody: { "recipient": "8261937452018734" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.inbox_api import InboxApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: inbox_api = InboxApi(api_client) response = await inbox_api.create_conversation( "acc_YOUR_FACEBOOK_ACCOUNT_ID", create_conversation_body={ "recipient": "8261937452018734" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/conversations" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "recipient": "8261937452018734" }' ``` **Response** ```json { "id": "cnv_9Xc4Vb7Nm2Lk5Jh8Gf1Ds6Az3Qw0Er9Ty4Ui7Op2As5Df8Gh1Jk6Lz3Xc0Vb9Nm4Qw7Er2Ty5Ui8Op1As6Df3Gh0Jk", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "members": [ { "id": "104987654321098", "username": null, "displayName": null }, { "id": "8261937452018734", "username": null, "displayName": null } ], "muted": false, "unreadCount": 0, "lastMessage": null } ``` Until a new conversation has its first message, you get `CONVO_NOT_FOUND`. With `attachmentUrl` or `cards`, no text shows. With `buttons`, text stops at 640. [Inbox webhooks](/docs/webhooks/inbox) include `message.delivered`, but not unsent messages. ### Messenger Setup [#messenger-setup] A Page can show up to 4 ice breakers and a menu of up to 3 items. See [Messenger Profile](/docs/inbox#messenger-profile) for the full request and its fields. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.setMessengerProfile({ id: "acc_YOUR_FACEBOOK_ACCOUNT_ID", setMessengerProfileBody: { "iceBreakers": [ { "question": "What are your opening hours?", "payload": "HOURS" }, { "question": "Do you deliver?", "payload": "DELIVERY" } ], "persistentMenu": [ { "type": "web_url", "title": "Order online", "url": "https://example.com/order" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.set_messenger_profile( "acc_YOUR_FACEBOOK_ACCOUNT_ID", set_messenger_profile_body={ "iceBreakers": [ { "question": "What are your opening hours?", "payload": "HOURS" }, { "question": "Do you deliver?", "payload": "DELIVERY" } ], "persistentMenu": [ { "type": "web_url", "title": "Order online", "url": "https://example.com/order" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X PUT "https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/messenger-profile" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "iceBreakers": [ { "question": "What are your opening hours?", "payload": "HOURS" }, { "question": "Do you deliver?", "payload": "DELIVERY" } ], "persistentMenu": [ { "type": "web_url", "title": "Order online", "url": "https://example.com/order" } ] }' ``` **Response** ```json { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "iceBreakers": [ { "question": "What are your opening hours?", "payload": "HOURS" }, { "question": "Do you deliver?", "payload": "DELIVERY" } ], "persistentMenu": [ { "type": "web_url", "title": "Order online", "url": "https://example.com/order", "payload": null } ] } ``` A tap on an ice breaker or `postback` item sends `message.postback`. ## Analytics [#analytics] ### Metrics [#metrics] | Field | Facebook metric | Notes | | --- | --- | --- | | `impressions` | `post_media_view` | | | `reach` | `post_total_media_view_unique` | | | `views` | `post_video_views` | Only `video` and `stories` | | `likes` | Likes | Else total reactions | | `comments` | Comments | | | `shares` | Shares | | | `saves` | None | Always `null` | | `engagement` | Likes + comments + shares | A count | ### Read Post Analytics [#read-post-analytics] **TypeScript** ```typescript import { Configuration, AnalyticsApi } from "@onepostly/sdk"; const analyticsApi = new AnalyticsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await analyticsApi.getPostAnalytics({ id: "pst_YOUR_FACEBOOK_POST", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.analytics_api import AnalyticsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: analytics_api = AnalyticsApi(api_client) response = await analytics_api.get_post_analytics( "pst_YOUR_FACEBOOK_POST", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts/pst_YOUR_FACEBOOK_POST/analytics" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_YOUR_FACEBOOK_POST", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "status": "ready", "metrics": { "impressions": 1234, "reach": 987, "likes": 123, "comments": 12, "shares": 4, "saves": null, "views": null, "engagement": 139 }, "fetchedAt": "2027-03-15T10:00:00.000Z", "error": null } ``` A fresh post often reads `pending`. A deleted one reads `unavailable`, for good. Stories update about hourly while live, then keep their last values. ### Account Stats [#account-stats] [Get Account Stats](/docs/api-reference/accounts/get-account-stats) returns live Page numbers. `followerCount` falls back to likes. `followingCount` and `videoCount` are `null`. ### Page Reviews [#page-reviews] [List Page Reviews](/docs/api-reference/facebook/list-account-reviews) lists recommendations, newest first. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.listAccountReviews({ id: "acc_YOUR_FACEBOOK_ACCOUNT_ID", limit: 20, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.list_account_reviews( "acc_YOUR_FACEBOOK_ACCOUNT_ID", limit=20, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/reviews?limit=20" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "1093847561029384", "recommendation": "positive", "rating": null, "text": "Friendly staff and the best sourdough in the neighborhood.", "reviewerName": "Jane Doe", "createdAt": "2027-03-14T16:20:00.000Z" }, { "id": "1093847561027710", "recommendation": "negative", "rating": null, "text": "Waited 20 minutes for a coffee on Saturday.", "reviewerName": null, "createdAt": "2027-03-09T11:05:00.000Z" }, { "id": "1093847561015526", "recommendation": null, "rating": 5, "text": null, "reviewerName": "Sam Lee", "createdAt": "2018-06-02T08:45:00.000Z" } ], "nextCursor": "QVFIUjRtNWdLbGd6UXBVZAk1jY0FfTnJ3dkx2S0RxZAXhOQmZAPNnV5dE1CSmVvUHg", "hasMore": true } ``` `recommendation` is `positive` or `negative`, and `rating` is the legacy 1 to 5 stars. Any field can be `null`. A new review sends a [`review.received`](/docs/webhooks/reviews) webhook. ### Account Insights [#account-insights] [Get Account Analytics](/docs/api-reference/analytics/get-account-analytics) reads Page Insights live. **TypeScript** ```typescript import { Configuration, AnalyticsApi } from "@onepostly/sdk"; const analyticsApi = new AnalyticsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await analyticsApi.getAccountAnalytics({ id: "acc_YOUR_FACEBOOK_ACCOUNT_ID", metrics: "page_media_view", period: "day", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.analytics_api import AnalyticsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: analytics_api = AnalyticsApi(api_client) response = await analytics_api.get_account_analytics( "acc_YOUR_FACEBOOK_ACCOUNT_ID", metrics="page_media_view", period="day", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/analytics?metrics=page_media_view&period=day" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "metrics": [ { "name": "page_media_view", "period": "day", "values": [ { "value": 3412, "endTime": "2027-03-14T07:00:00.000Z" }, { "value": 2987, "endTime": "2027-03-15T07:00:00.000Z" } ] } ], "demographics": {} } ``` | Parameter | Facebook values | | --- | --- | | `metrics` | Up to 20 Page Insights metric names | | `period` | `day` (default), `week`, `days_28`, `lifetime` | | `since`, `until` | A [time window](/docs/pagination#time-filters) | - The defaults are `page_media_view`, `page_total_media_view_unique`, `page_post_engagements`, `page_follows` and `page_daily_follows_unique`. - `demographics` is always empty. Instagram-only parameters are ignored. - A retired metric fails the read with `400`. The message names it. ### Recent Posts [#recent-posts] [List Account Media](/docs/api-reference/accounts/list-account-media) lists recent posts. Its `metrics` are `null`. ## Limitations [#limitations] Not available for Facebook through Onepostly. - Profiles and Groups - Editing published posts, sharing and reposting - Live and Events - Story captions, links, stickers and comments - Message tags after 24 hours - Saves and demographics ## Errors [#errors] Breaking a rule on this page returns `400 VALIDATION_ERROR` and creates nothing. Every code is listed in [Errors](/docs/error-handling), with its cause and fix. ### Publish Errors [#publish-errors] | Code | Cause | Fix | | --- | --- | --- | | `TEXT_REQUIRED` | A text post with no text or `link` | Add one | | `INVALID_MULTI_IMAGE` | Over 10 images | Send 2 to 10 | | `INVALID_MEDIA` | A video in an album, a non-video Reel, or too large | See [Media Requirements](#media-requirements) | | `INVALID_CAROUSEL` | Cards without `multi_image`, or a wrong count | One card per image | | `TEXT_FORMAT_UNSUPPORTED` | A text background on a media post | Use it on text posts | | `REEL_UPLOAD_FAILED`, `STORY_UPLOAD_FAILED` | Facebook did not open the upload | Post again | | `PERMISSION_DENIED` | No publish permission or Page role | Reconnect, or get content access | | `DELETE_PERMISSION` | Facebook refused the delete | Reconnect with every permission | ### Engagement and Inbox Errors [#engagement-and-inbox-errors] | Code | Cause | Fix | | --- | --- | --- | | `POST_ACCOUNT_MISMATCH` | Another Page's `pst_` id | Use the Facebook id | | `UNSUPPORTED_MEDIA` | Comments on a Story | Stories have none | | `COMMENTS_PERMISSION` | The Page may not act on the comment | Reconnect with every permission | | `PRIVATE_REPLY_FAILED` | A second reply, or after 7 days | One per comment, within 7 days | | `RECIPIENT_NOT_FOUND` | Not a valid PSID | Use a numeric PSID | | `MESSAGE_WINDOW_EXPIRED` | Over 24 hours since their message | Wait for them to write | | `INBOX_PERMISSION` | No messaging permission or role | Reconnect, or get message access | | `PROFILE_FAILED` | Ice breakers or menu did not save | Read the message | ### Analytics Errors [#analytics-errors] | Code | Cause | Fix | | --- | --- | --- | | `ANALYTICS_PENDING` | No metrics yet | Read again later | | `POST_NOT_FOUND` | Deleted on Facebook | None, this is final | | `ANALYTICS_PERMISSION` | No insights permission or role | Reconnect, or get insights access | | `REVIEWS_FAILED` | Reviews did not load | Read again later | # Instagram (/docs/instagram) Publish photos, carousels, Reels and Stories, answer comments and direct messages, and read post and account analytics. ## Quick Reference [#quick-reference] | Property | Value | | ------------------ | ------------------------------------------------------------------------ | | Account types | Business or Creator accounts | | Connection method | OAuth, Instagram Login or Facebook Login | | Post types | `image`, `multi_image`, `video` (published as `reel`), `reel`, `stories` | | Max media per post | 10 | | Text limit | 2,200 characters | | Threads | No | | Quotes | No | | Remote delete | Yes (Facebook Login only) | | Comments | Yes | | Likes | No | | Reposts | No | | Bookmarks | No | | Direct messages | Yes | | Post analytics | Yes | | Account analytics | Yes (Stats and insights) | Every post needs media. `video` and `reel` publish the same Reel. Deleting posts, catalog audio and the paid partnership label need [Facebook Login](#login-methods). ## Connect [#connect] You need a Business or Creator account, not a personal one. Connect it in **Dashboard → Connections**, or from your app with a connect session for `platform: "instagram"`, as described in [Connect Accounts](/docs/connection). ### Login Methods [#login-methods] `loginMethod` defaults to `instagram_login`. Facebook Login needs a linked Facebook Page and unlocks the extra features below. | Feature | Instagram Login | Facebook Login | | --- | --- | --- | | Publish, comments, messages, analytics | Yes | Yes | | [Catalog audio](#catalog-audio) on Reels | No | Yes | | [Paid partnership](#paid-partnership) label | No | Yes | | Delete published posts | No | Yes | On Instagram Login, those options return `400 VALIDATION_ERROR`. **TypeScript** ```typescript import { Configuration, ConnectApi } from "@onepostly/sdk"; const connectApi = new ConnectApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await connectApi.createConnectSession({ createConnectSessionBody: { "platform": "instagram", "loginMethod": "facebook_login", "redirectUrl": "https://app.example.com/onepostly/connected" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.connect_api import ConnectApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: connect_api = ConnectApi(api_client) response = await connect_api.create_connect_session( create_connect_session_body={ "platform": "instagram", "loginMethod": "facebook_login", "redirectUrl": "https://app.example.com/onepostly/connected" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/connect-sessions" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "platform": "instagram", "loginMethod": "facebook_login", "redirectUrl": "https://app.example.com/onepostly/connected" }' ``` **Response** ```json { "url": "https://www.facebook.com/v26.0/dialog/oauth?client_id=2938475610293847&response_type=code&scope=instagram_basic%2Cinstagram_content_publish%2Cinstagram_manage_comments%2Cinstagram_manage_insights%2Cinstagram_manage_messages%2Cinstagram_manage_contents%2Cpages_show_list%2Cpages_read_engagement%2Cbusiness_management%2Cpublic_profile&state=eyJwIjoiaW5zdGFncmFtIiwibiI6IjNmOWMxYTJiIn0.Xk2pQ8vRt4mN7sL1&auth_type=rerequest", "expiresAt": "2027-03-15T09:10:00.000Z" } ``` Facebook Login shows an account picker of the Instagram accounts linked to the person's Pages. For your own picker, add `headless: true`, see [Pick a Page or Account](/docs/connection#pick-a-page-or-account). To switch an account to Facebook Login, connect it again. ### Permissions [#permissions] **Instagram Login** | Scope | Used for | | --- | --- | | `instagram_business_basic` | Id, username and avatar | | `instagram_business_content_publish` | Publishing | | `instagram_business_manage_comments` | Comments | | `instagram_business_manage_insights` | Analytics | | `instagram_business_manage_messages` | Messages and private replies | **Facebook Login** | Scope | Used for | | --- | --- | | `instagram_basic` | Id, username and avatar | | `instagram_content_publish` | Publishing | | `instagram_manage_comments` | Comments | | `instagram_manage_insights` | Analytics | | `instagram_manage_messages` | Messages and private replies | | `instagram_manage_contents` | Deleting posts | | `pages_show_list`, `pages_read_engagement` | Finding the linked Page | | `business_management` | Pages in a Business portfolio | | `public_profile` | Facebook sign-in | ### Staying Connected [#staying-connected] Access renews itself, so `canAutoRenew` is `true`. You only need to [reconnect](/docs/account-status#reconnect-an-account) in the cases below, and the account id stays the same. - `status` is not `active`, or you get `TOKEN_INVALID`, such as after a password change. - A `*_PERMISSION` code, which a reconnect grants. - `CONNECTION_BROKEN` on Facebook Login, when the Page is unlinked. ## Publish [#publish] **TypeScript** ```typescript 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": "Golden hour at the harbor #sunset", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/harbor.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Golden hour at the harbor #sunset", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/harbor.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Golden hour at the harbor #sunset", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/harbor.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "publishing", "text": "Golden hour at the harbor #sunset", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/harbor.jpg" } ], "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" } ] } ``` Once published, `url` is the Instagram permalink. See [Post Status](/docs/post-lifecycle#post-status). ### Post Types [#post-types] | `mediaKind` | Publishes | Media | | --- | --- | --- | | `image` | Feed photo | 1 image | | `multi_image` | Carousel | 2 to 10 images or videos, mixed | | `video`, `reel` | Reel | 1 video | | `stories` | Story, for 24 hours | 1 image or video | - Captions go up to 2,200 characters. Stories show no caption. - The files set the kind, so set `mediaKind` only for `stories`. - A Reel always reads `mediaKind: "reel"`, even sent as `video`. - A carousel follows the order of `media`. Over 10 items fails with `INVALID_MULTI_IMAGE`. #### Reel [#reel] A Reel shows on the Reels tab and the grid. `shareToFeed: false` keeps it off the grid. The cover is `coverUrl` or the `thumbOffset` frame, and `coverUrl` wins. `audioName` sets a new name for the audio, once. Reel options work only on `reel` or `video`. Elsewhere, including a video in a carousel or Story, they return `400 VALIDATION_ERROR`. **TypeScript** ```typescript 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": "How we pack an order in 30 seconds", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/packing.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "coverUrl": "https://cdn.onepostly.com/media/packing-cover.jpg", "audioName": "Packing day" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "How we pack an order in 30 seconds", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/packing.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "coverUrl": "https://cdn.onepostly.com/media/packing-cover.jpg", "audioName": "Packing day" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "How we pack an order in 30 seconds", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/packing.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "coverUrl": "https://cdn.onepostly.com/media/packing-cover.jpg", "audioName": "Packing day" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "publishing", "text": "How we pack an order in 30 seconds", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/packing.mp4" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "instagram": { "coverUrl": "https://cdn.onepostly.com/media/packing-cover.jpg", "audioName": "Packing day" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` #### Story [#story] A Story takes only `userTags`. Any other option returns `400 VALIDATION_ERROR`. Stories have no comments, so a comment list returns `UNSUPPORTED_MEDIA`. **TypeScript** ```typescript import { Configuration, PostsApi } from "@onepostly/sdk"; const postsApi = new PostsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await postsApi.createPost({ createPostBody: { "mediaKind": "stories", "media": [ { "url": "https://cdn.onepostly.com/media/flash-sale.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "mediaKind": "stories", "media": [ { "url": "https://cdn.onepostly.com/media/flash-sale.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "mediaKind": "stories", "media": [ { "url": "https://cdn.onepostly.com/media/flash-sale.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "publishing", "text": "", "mediaKind": "stories", "media": [ { "url": "https://cdn.onepostly.com/media/flash-sale.jpg" } ], "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" } ] } ``` ### Options [#options] Options go under `instagram`. On the wrong media kind, they return `400`. | Field | Type | Description | | ----------------------------------- | ------------------------------------------------ | --------------------------------------------------------------------------- | | `accountId` (required) | `string` | The Instagram account id. | | `text` | `string` | This account's caption, up to 2,200 characters. | | `instagram.firstComment` | `string` | A comment posted after publish, up to 2,200 characters. | | `instagram.commentsEnabled` | `boolean` | false turns comments off after publish. | | `instagram.userTags` | `{ username: string; x?: number; y?: number }[]` | Up to 20 tagged accounts. See Tags. | | `instagram.collaborators` | `string[]` | Up to 3 co-author usernames. | | `instagram.locationId` | `string` | The id of a Facebook Page with a location. | | `instagram.isAiGenerated` | `boolean` | Shows the AI label. Default `false`. | | `instagram.isPaidPartnership` | `boolean` | Shows the Paid partnership label. Facebook Login only. Default `false`. | | `instagram.brandedContentSponsors` | `string[]` | Up to 2 sponsors, by username or user id. Facebook Login only. | | `instagram.shareToFeed` | `boolean` | Reels only. false keeps it off the grid. Default `true`. | | `instagram.coverUrl` | `string` | Reels only. A cover image URL. | | `instagram.thumbOffset` | `integer` | Reels only. The cover frame in milliseconds, up to 60,000. | | `instagram.audioName` | `string` | Reels only. A new audio name, up to 200 characters. | | `instagram.trialReel` | `boolean` | Reels only. Shows it to non-followers first. Default `false`. | | `instagram.trialGraduationStrategy` | `"manual" \| "ss_performance"` | Reels only. Needs trialReel. See Trial Reels. Default `"manual"`. | | `instagram.audioId` | `string` | Reels only. A catalog track id. Facebook Login only. | | `instagram.audioVolume` | `integer` | Reels only. Track volume, 1 to 100. Needs audioId. Default `100`. | | `instagram.videoVolume` | `integer` | Reels only. The video's own volume, 1 to 100. Needs audioId. Default `100`. | `firstComment`, `commentsEnabled`, `collaborators`, `locationId`, `isAiGenerated` and the paid partnership fields work on photos, carousels and Reels. If Instagram refuses `firstComment` or `commentsEnabled`, the post still publishes. #### Tags and Location [#tags-and-location] `userTags` takes a `username`, `@` optional, and `x` and `y` from 0 to 1, from the top left. A photo needs `x` and `y`. Without them it passes on create but fails at publish. They are optional on Stories and ignored on Reels. `locationId` and tags cover a whole carousel. **TypeScript** ```typescript 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": "Opening night with the team", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/opening.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "userTags": [ { "username": "studio.north", "x": 0.32, "y": 0.6 } ], "collaborators": [ "studio.north" ], "locationId": "110843418940484" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Opening night with the team", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/opening.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "userTags": [ { "username": "studio.north", "x": 0.32, "y": 0.6 } ], "collaborators": [ "studio.north" ], "locationId": "110843418940484" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Opening night with the team", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/opening.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "userTags": [ { "username": "studio.north", "x": 0.32, "y": 0.6 } ], "collaborators": [ "studio.north" ], "locationId": "110843418940484" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "publishing", "text": "Opening night with the team", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/opening.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "instagram": { "userTags": [ { "username": "studio.north", "x": 0.32, "y": 0.6 } ], "collaborators": [ "studio.north" ], "locationId": "110843418940484" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` #### Trial Reels [#trial-reels] `trialReel: true` shows a Reel to non-followers first. | `trialGraduationStrategy` | Followers see it when | | --- | --- | | `manual` (default) | You share it in the Instagram app | | `ss_performance` | It performs well | A trial Reel with sponsors fails with `INVALID_TRIAL_REEL`. #### Catalog Audio [#catalog-audio] `audioId` adds a track to a Reel on Facebook Login. Find ids with [Search Instagram Audio](/docs/api-reference/instagram/search-account-audio). Omit `q` for trending tracks or set `type=original_sound`. **TypeScript** ```typescript 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": "Weekend mood", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/beach.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "audioId": "587784541076604", "audioVolume": 80, "videoVolume": 30 } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Weekend mood", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/beach.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "audioId": "587784541076604", "audioVolume": 80, "videoVolume": 30 } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Weekend mood", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/beach.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "audioId": "587784541076604", "audioVolume": 80, "videoVolume": 30 } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "publishing", "text": "Weekend mood", "mediaKind": "reel", "media": [ { "url": "https://cdn.onepostly.com/media/beach.mp4" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "instagram": { "audioId": "587784541076604", "audioVolume": 80, "videoVolume": 30 } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` #### Paid Partnership [#paid-partnership] On Facebook Login, `isPaidPartnership: true` adds the label. `brandedContentSponsors` adds it with up to 2 named sponsors. A sponsor username must be a public professional account, or the post fails with `INVALID_SPONSOR`. A numeric id always works. **TypeScript** ```typescript 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": "Our new spring line, made with Fieldwork", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/spring-1.jpg" }, { "url": "https://cdn.onepostly.com/media/spring-2.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "brandedContentSponsors": [ "fieldwork.co" ] } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Our new spring line, made with Fieldwork", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/spring-1.jpg" }, { "url": "https://cdn.onepostly.com/media/spring-2.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "brandedContentSponsors": [ "fieldwork.co" ] } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Our new spring line, made with Fieldwork", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/spring-1.jpg" }, { "url": "https://cdn.onepostly.com/media/spring-2.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "instagram": { "brandedContentSponsors": [ "fieldwork.co" ] } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "publishing", "text": "Our new spring line, made with Fieldwork", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/spring-1.jpg" }, { "url": "https://cdn.onepostly.com/media/spring-2.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "instagram": { "brandedContentSponsors": [ "fieldwork.co" ] } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` ### Media Requirements [#media-requirements] These are Instagram's limits, on top of the [Media URL Requirements](/docs/media-uploads#media-url-requirements). #### Images [#images] | Property | Requirement | | --- | --- | | Format | JPEG | | Max size | 8 MB | | Aspect ratio | 4:5 to 1.91:1 on feed and carousel | | Width | 320 to 1440, resized outside it | | Common sizes | 1080 × 1350, 1080 × 1080, 1080 × 566 | | Stories | 1080 × 1920 (9:16) | A 3:4 image, such as 1080 × 1440, is too narrow for the feed. #### Videos [#videos] | Property | Reel | Story | | --- | --- | --- | | Formats | MP4, MOV | MP4, MOV | | Max size | 300 MB | 100 MB | | Duration | 3 s to 15 min | 3 to 60 s | | Aspect ratio | 9:16 | 9:16 | | Max width | 1920 | 1920 | | Video | H.264 or HEVC, 23 to 60 fps | Same | | Audio | AAC, up to 48 kHz | Same | A URL ending in `.mp4`, `.mov`, `.m4v`, `.webm` or `.avi` is a video, anything else an image. Slow processing fails with `MEDIA_PROCESSING_TIMEOUT`. ### Scheduling, Editing and Deleting [#scheduling-editing-and-deleting] [Scheduling and editing](/docs/scheduling) work as usual. Published posts cannot be edited. Only Facebook Login can [delete](/docs/post-lifecycle#delete-a-post) a published post. Instagram Login returns `MEDIA_DELETE_UNSUPPORTED`, so delete it in the app. Posts made outside Onepostly cannot be deleted and return `409 NOT_DELETABLE`. ## Engagement [#engagement] See [Comments](/docs/comments) for the requests. Instagram has no likes, reposts or bookmarks. | Action | Supported | Notes | | --- | --- | --- | | List comments | Yes | Not on Stories, which return `UNSUPPORTED_MEDIA` | | Comment or reply | Yes | Up to 2,200 characters | | Delete a comment | Yes | On the account's own media | | Hide or unhide | Yes | | | Private reply | Yes | One per comment, within 7 days, up to 1,000 characters | | Like a comment | No | `UNSUPPORTED_PLATFORM` | | Like, repost, bookmark | No | `UNSUPPORTED_PLATFORM` | Outside posts work once [synced](/docs/publishing#posts-made-outside-onepostly). New comments send [`comment.received`](/docs/webhooks/comments). **TypeScript** ```typescript import { Configuration, CommentsApi } from "@onepostly/sdk"; const commentsApi = new CommentsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await commentsApi.sendPrivateReply({ id: "cmt_YOUR_COMMENT", privateReplyBody: { "text": "Hi! Here is the size chart you asked about." }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.comments_api import CommentsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: comments_api = CommentsApi(api_client) response = await comments_api.send_private_reply( "cmt_YOUR_COMMENT", private_reply_body={ "text": "Hi! Here is the size chart you asked about." }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/comments/cmt_YOUR_COMMENT/private-reply" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Hi! Here is the size chart you asked about." }' ``` **Response** ```json { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAwMTIzNDU2Nzg5OjM0MDI4MjM2Njg0MTcxMDMwMTI0NDI1OTc5NjAzNjg0NTQ0NDQ1NgZDZD", "commentId": "cmt_YOUR_COMMENT", "text": "Hi! Here is the size chart you asked about.", "createdAt": "2027-03-15T10:00:00.000Z" } ``` ## Inbox [#inbox] Both logins have an inbox. See [Inbox](/docs/inbox) for the requests and rich messages. | Action | Supported | Notes | | --- | --- | --- | | List and read | Yes | `muted` is always `false` | | Start a conversation | Yes | By username or user id | | Send text | Yes | Up to 1,000 characters, within 24 hours | | Rich messages | Yes | Attachments, quick replies, buttons, cards | | [Automations](/docs/automations) | Yes | A `comment_to_dm` uses the comment's private reply | | Outside the 24-hour window | No | | Use a username for public professional accounts, or else a `senderId`. **TypeScript** ```typescript import { Configuration, InboxApi } from "@onepostly/sdk"; const inboxApi = new InboxApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await inboxApi.createConversation({ id: "acc_YOUR_INSTAGRAM_ACCOUNT_ID", createConversationBody: { "recipient": "17841400987654321" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.inbox_api import InboxApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: inbox_api = InboxApi(api_client) response = await inbox_api.create_conversation( "acc_YOUR_INSTAGRAM_ACCOUNT_ID", create_conversation_body={ "recipient": "17841400987654321" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/accounts/acc_YOUR_INSTAGRAM_ACCOUNT_ID/conversations" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "recipient": "17841400987654321" }' ``` **Response** ```json { "id": "cnv_BBh0Fb9Jm3kot2rw9sXz01Wph6BsppQzHdFeEz3M57nTn5Hq1Vaxue9BreJNIcZngbmoCxHC", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "members": [ { "id": "17841400123456789", "username": null, "displayName": null }, { "id": "17841400987654321", "username": null, "displayName": null } ], "muted": false, "unreadCount": 0, "lastMessage": null } ``` A new conversation opens with its first message. Until then you get `CONVO_NOT_FOUND`. The person must have written in the last 24 hours, or you get `MESSAGE_WINDOW_EXPIRED` and must wait for them to write. With `attachmentUrl`, Instagram shows only the attachment and not your text, so send anything important as its own message. [Inbox webhooks](/docs/webhooks/inbox) cover received, sent, read, reactions, postbacks and unsent messages. Their `conversationId` may differ from List Conversations, and both work everywhere. See [Conversation Ids](/docs/inbox#conversation-ids) for which call returns which. ## Analytics [#analytics] ### Metrics [#metrics] | Field | Instagram metric | Notes | | --- | --- | --- | | `impressions` | `views` | Instagram dropped impressions | | `reach` | `reach` | Unique accounts | | `views` | `views` | | | `likes` | `likes` | `null` on Stories | | `comments` | `comments` | `null` on Stories | | `shares` | `shares` | | | `saves` | `saved` | `null` on Stories | | `engagement` | `total_interactions` | A count. Else the sum of the four | A metric the media type lacks is `null`, not `0`. ### Read Post Analytics [#read-post-analytics] **TypeScript** ```typescript import { Configuration, AnalyticsApi } from "@onepostly/sdk"; const analyticsApi = new AnalyticsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await analyticsApi.getPostAnalytics({ id: "pst_YOUR_INSTAGRAM_POST", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.analytics_api import AnalyticsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: analytics_api = AnalyticsApi(api_client) response = await analytics_api.get_post_analytics( "pst_YOUR_INSTAGRAM_POST", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts/pst_YOUR_INSTAGRAM_POST/analytics" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_YOUR_INSTAGRAM_POST", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "status": "ready", "metrics": { "impressions": 2140, "reach": 1630, "likes": 184, "comments": 21, "shares": 9, "saves": 37, "views": 2140, "engagement": 251 }, "fetchedAt": "2027-03-15T10:00:00.000Z", "error": null } ``` Outside posts work once [synced](/docs/publishing#posts-made-outside-onepostly). A fresh post often reads `pending`. A deleted one reads `unavailable` with `POST_NOT_FOUND`, for good. Posts follow the shared [freshness](/docs/analytics#freshness). Stories update about hourly while live, then keep their last values. ### Account Stats [#account-stats] [Get Account Stats](/docs/api-reference/accounts/get-account-stats) returns the account's live counts. `videoCount` counts all media, photos included. `likesCount` is always `null`. ### Account Insights [#account-insights] [Get Account Analytics](/docs/api-reference/analytics/get-account-analytics) reads insights live. By default it returns `views`, `reach`, `accounts_engaged` and `total_interactions`. See [Account Insights](/docs/analytics#account-insights). **TypeScript** ```typescript import { Configuration, AnalyticsApi } from "@onepostly/sdk"; const analyticsApi = new AnalyticsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await analyticsApi.getAccountAnalytics({ id: "acc_YOUR_INSTAGRAM_ACCOUNT_ID", metrics: "follower_demographics", period: "lifetime", breakdown: "country", timeframe: "this_month", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.analytics_api import AnalyticsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: analytics_api = AnalyticsApi(api_client) response = await analytics_api.get_account_analytics( "acc_YOUR_INSTAGRAM_ACCOUNT_ID", metrics="follower_demographics", period="lifetime", breakdown="country", timeframe="this_month", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_INSTAGRAM_ACCOUNT_ID/analytics?metrics=follower_demographics&period=lifetime&breakdown=country&timeframe=this_month" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "metrics": [ { "name": "follower_demographics", "period": "lifetime", "values": [] } ], "demographics": { "follower_demographics": { "US": 4120, "GB": 1380, "DE": 960, "TR": 845, "BR": 610 } } } ``` | Parameter | Instagram values | | --- | --- | | `metrics` | Up to 20 Instagram metric names | | `period` | `day` (default), `week`, `days_28`, `lifetime` | | `breakdown` | `age`, `city`, `country`, `gender`, or a metric's own breakdown | | `timeframe` | `this_week` or `this_month` | | `metricType` | `total_value` or `time_series` | - Demographics are `follower_demographics` and `engaged_audience_demographics`. - They need `period=lifetime`, a `breakdown` and a `timeframe`. - `follower_count` and `online_followers` come only as a daily series. - Leave out `metricType` to get each metric in its native form. - A value Instagram refuses returns `400 VALIDATION_ERROR` with its reason. ### Recent Posts [#recent-posts] [List Account Media](/docs/api-reference/accounts/list-account-media) lists recent posts with likes and comments. Their `shares` and `views` are `null`. Add `kind=stories` for active Stories. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.listAccountMedia({ id: "acc_YOUR_INSTAGRAM_ACCOUNT_ID", kind: "stories", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.list_account_media( "acc_YOUR_INSTAGRAM_ACCOUNT_ID", kind="stories", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_INSTAGRAM_ACCOUNT_ID/media?kind=stories" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "18063412987650214", "title": null, "description": null, "coverUrl": "https://scontent.cdninstagram.com/v/t51.29350-15/story-thumbnail.jpg", "url": "https://www.instagram.com/stories/yourbrand/3581234567890123456/", "createdAt": "2027-03-15T08:30:00.000Z", "durationSec": null, "metrics": { "likes": null, "comments": null, "shares": null, "views": null } }, { "id": "18047129563820471", "title": null, "description": null, "coverUrl": null, "url": "https://www.instagram.com/stories/yourbrand/3580987654321098765/", "createdAt": "2027-03-14T19:05:00.000Z", "durationSec": null, "metrics": { "likes": null, "comments": null, "shares": null, "views": null } } ], "nextCursor": null, "hasMore": false } ``` ## Limitations [#limitations] Not available for Instagram through Onepostly. - Text-only posts - Editing a published post - Likes, reposts, quotes, bookmarks and threads - Comments on Stories - Story stickers, product tags and Live - Messages outside the 24-hour window - Deletes, catalog audio and paid partnership on Instagram Login ## Errors [#errors] Breaking a rule on this page returns `400 VALIDATION_ERROR` and creates nothing. Instagram's own limits are checked at publish and fail the post. The tables below list the Instagram codes, and every code is in [Errors](/docs/error-handling). ### Publish Errors [#publish-errors] | Code | Cause | Fix | | --- | --- | --- | | `INVALID_MULTI_IMAGE` | Over 10 carousel items | Send 2 to 10 | | `INVALID_TRIAL_REEL` | A trial Reel with sponsors | Drop the sponsors | | `INVALID_AUDIO` | `audioId`, but the account moved to Instagram Login | Reconnect with Facebook Login | | `INVALID_SPONSOR` | A sponsor is not public and professional, or the account moved to Instagram Login | Use a numeric id, or Facebook Login | | `INVALID_MEDIA` | Instagram rejected the file | See [Media Requirements](#media-requirements) | | `CONTAINER_FAILED` | Instagram could not process the media | Check format, size and dimensions | | `MEDIA_PROCESSING_TIMEOUT` | The video took too long | Use a smaller or shorter file | | `MEDIA_DELETE_UNSUPPORTED` | A delete on Instagram Login | Use Facebook Login, or the app | | `DELETE_PERMISSION` | Instagram refused the delete | Reconnect with Facebook Login | | `PUBLISH_FAILED` | Instagram rejected the post | Read `error.message` | ### Engagement and Inbox Errors [#engagement-and-inbox-errors] | Code | Cause | Fix | | --- | --- | --- | | `UNSUPPORTED_MEDIA` | The post is a Story | Use a photo, carousel or Reel | | `UNSUPPORTED_PLATFORM` | A like, repost or bookmark | Not offered on Instagram | | `COMMENTS_PERMISSION` | A missing permission, or not your media | Reconnect, or delete only your own | | `PRIVATE_REPLY_FAILED` | A second reply, or after 7 days | One per comment, within 7 days | | `RECIPIENT_NOT_FOUND` | The username is not public and professional | Use the numeric user id | | `RECIPIENT_UNREACHABLE` | The person blocked or turned off messages | Wait for them to write | | `CONVO_NOT_FOUND` | No conversation, or no message yet | Send the first message | | `MESSAGE_WINDOW_EXPIRED` | Their last message is over 24 hours old | Wait for them to write | | `CONNECTION_BROKEN` | Facebook Login lost its Page | Reconnect and pick the Page | ### Analytics Errors [#analytics-errors] | Code | Cause | Fix | | --- | --- | --- | | `ANALYTICS_PENDING` | No metrics yet | Read again later | | `POST_NOT_FOUND` | Deleted on Instagram | None, this is final | | `VALIDATION_ERROR` | Instagram refused an insights parameter | Fix the one in the message | | `STATS_FAILED` | Stats did not load | Read again later | # LinkedIn (/docs/linkedin) Publish text, images, video and documents as a LinkedIn member. ## Quick Reference [#quick-reference] | Property | Value | | ------------------ | --------------------------------------------------- | | Account types | Personal profiles, not company pages | | Connection method | OAuth | | Post types | `text`, `image`, `multi_image`, `video`, `document` | | Max media per post | 20 | | Text limit | 3,000 characters | | Threads | No | | Quotes | No | | Remote delete | Yes | | Comments | No | | Likes | No | | Reposts | No | | Bookmarks | No | | Direct messages | No | | Post analytics | No | | Account analytics | No | Only personal profiles connect, and every post is public. LinkedIn has no comments, likes, inbox or analytics here, but takes a [first comment](#first-comment). ## Connect [#connect] Connect in **Dashboard → Connections**, or with a [connect session](/docs/connection). Each account posts as one member. Other members connect their own accounts. ### Permissions [#permissions] | Scope | Used for | | --- | --- | | `openid` | LinkedIn sign-in | | `profile` | Name and photo | | `w_member_social` | Posting, media, first comments and deletes | ### Staying Connected [#staying-connected] `canAutoRenew` tells you when to reconnect. | `canAutoRenew` | Access | Reconnect | | --- | --- | --- | | `true` | Renews itself for up to 1 year | When `status` leaves `active`, or within a year | | `false` | Ends at `tokenExpiresAt`, after 60 days | Before `tokenExpiresAt` | > **Scheduled posts need a live account** > > > A post due after access ends fails with `TOKEN_INVALID`. Check `tokenExpiresAt` before you schedule, and reconnect if the post is due later. Each reconnect starts a new 60 days. Access also ends if the member removes Onepostly. A [reconnect](/docs/account-status#reconnect-an-account) keeps the id. Then publish failed posts again. ## Publish [#publish] **TypeScript** ```typescript 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": "The 2027 State of Social Publishing report", "mediaKind": "document", "media": [ { "url": "https://cdn.onepostly.com/media/state-of-publishing-2027.pdf" } ], "accounts": [ { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "The 2027 State of Social Publishing report", "mediaKind": "document", "media": [ { "url": "https://cdn.onepostly.com/media/state-of-publishing-2027.pdf" } ], "accounts": [ { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "The 2027 State of Social Publishing report", "mediaKind": "document", "media": [ { "url": "https://cdn.onepostly.com/media/state-of-publishing-2027.pdf" } ], "accounts": [ { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "platform": "linkedin", "source": "onepostly", "status": "publishing", "text": "The 2027 State of Social Publishing report", "mediaKind": "document", "media": [ { "url": "https://cdn.onepostly.com/media/state-of-publishing-2027.pdf" } ], "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" } ] } ``` A LinkedIn post has no `url`. Build it from `platformPostId`. The link is `https://www.linkedin.com/feed/update/` plus the `platformPostId`. ### Post Types [#post-types] | `mediaKind` | Publishes | Media | | --- | --- | --- | | `text` | Text post | None, `text` required | | `image` | Image post | 1 image | | `multi_image` | Image set | 2 to 20 images | | `video` | Video post | 1 video | | `document` | Swipeable document | 1 PDF, PPT, PPTX, DOC or DOCX | - Text goes up to 3,000 characters. Without `mediaKind`, the [files decide](/docs/publishing#media-kinds). - `stories` returns `400 VALIDATION_ERROR`. - A video in an image set fails with `INVALID_MEDIA`. The first 200 characters of the text become a video or document title. A document without any text is titled `Document`. Videos take longer, and slow ones fail with `MEDIA_PROCESSING_TIMEOUT`. #### Text Formatting [#text-formatting] Text is posted exactly as written. `@name` stays plain text, with no mention. `*`, `_`, `~`, `|` and brackets show as typed too, not as formatting. `#word` becomes a hashtag, and line breaks are kept. #### Duplicate Content [#duplicate-content] LinkedIn rejects a repeat of a post the member already made. It fails with `PUBLISH_FAILED`. Change the text, then post again. ### Options [#options] Options go under `linkedin`. | Field | Type | Description | | ----------------------- | -------- | ------------------------------------------------ | | `accountId` (required) | `string` | The LinkedIn account id. | | `text` | `string` | This account's text, up to 3,000 characters. | | `linkedin.firstComment` | `string` | A comment after publish, up to 1,250 characters. | #### First Comment [#first-comment] `firstComment` adds a comment from the member, on any post type. If LinkedIn refuses the comment, the post still publishes without it. **TypeScript** ```typescript 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": "Version 3.0 is out.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/release-3.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "linkedin": { "firstComment": "Release notes: https://example.com/changelog" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Version 3.0 is out.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/release-3.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "linkedin": { "firstComment": "Release notes: https://example.com/changelog" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Version 3.0 is out.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/release-3.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "linkedin": { "firstComment": "Release notes: https://example.com/changelog" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "platform": "linkedin", "source": "onepostly", "status": "publishing", "text": "Version 3.0 is out.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/release-3.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "linkedin": { "firstComment": "Release notes: https://example.com/changelog" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` ### Media Requirements [#media-requirements] These are LinkedIn's limits, on top of the [Media URL Requirements](/docs/media-uploads#media-url-requirements). #### Images [#images] | Property | Requirement | | --- | --- | | Formats | JPG, PNG, GIF | | Max size | 30 MB | | Per post | 1, or 2 to 20 on `multi_image` | #### Videos [#videos] | Property | Requirement | | --- | --- | | Format | MP4 | | Size | 75 KB to 500 MB | | Duration | 3 s to 30 min | | Per post | 1, alone | #### Documents [#documents] | Property | Requirement | | --- | --- | | Formats | PDF, PPT, PPTX, DOC, DOCX | | Max size | 100 MB | | Max pages | 300 | | Per post | 1, alone | The URL must send a document `Content-Type`. See [Supported Formats](/docs/media-uploads#supported-formats). ### Scheduling, Editing and Deleting [#scheduling-editing-and-deleting] [Scheduling and editing](/docs/scheduling) work as usual. Published posts cannot be edited. With `canAutoRenew: false`, reconnect before any post due after `tokenExpiresAt`. [Deleting](/docs/post-lifecycle#delete-a-post) removes the post. A post already gone counts as deleted. ## Engagement [#engagement] LinkedIn has no comments, likes, reposts or bookmarks here. Those calls return `UNSUPPORTED_PLATFORM`. Use a [first comment](#first-comment) instead. ## Inbox [#inbox] LinkedIn has no inbox through Onepostly. ## Analytics [#analytics] LinkedIn reports no metrics here. A post reads `pending`, then `unsupported` for good. Account stats and insights return `UNSUPPORTED_PLATFORM`. ## Limitations [#limitations] Not available for LinkedIn through Onepostly. - Company pages - Polls, articles, reshares and quotes - Threads and Stories - Mentions, `@name` stays plain text - Visibility, every post is public - Custom video thumbnails or captions - Editing a published post - A post `url` - Comments, likes and messages - Analytics - [Sync](/docs/publishing#posts-made-outside-onepostly) of outside posts ## Errors [#errors] Breaking a rule on this page returns `400 VALIDATION_ERROR` and creates nothing. LinkedIn's own limits are checked at publish and fail with `INVALID_MEDIA`. Every code is in [Errors](/docs/error-handling), with its cause and fix. | Code | Cause | Fix | | --- | --- | --- | | `TEXT_REQUIRED` | A text post with no text | Add text or media | | `INVALID_MEDIA` | Too many files, mixed video, wrong size or type | See [Media Requirements](#media-requirements) | | `MEDIA_UPLOAD_FAILED` | LinkedIn could not take the file | Check it opens, then post again | | `MEDIA_PROCESSING_TIMEOUT` | The video took too long | Use a smaller or shorter file | | `PUBLISH_FAILED` | Rejected, such as a [duplicate](#duplicate-content) | Read `error.message` | | `QUOTA_EXCEEDED` | LinkedIn's daily post or delete limit | Try again after it resets | | `DELETE_PERMISSION` | LinkedIn refused the delete | Reconnect, then delete again | # Pinterest (/docs/pinterest) Publish image and video pins to a board, schedule them and delete them. ## Quick Reference [#quick-reference] | Property | Value | | ------------------ | ------------------------- | | Account types | Pinterest accounts | | Connection method | OAuth | | Post types | `image`, `video` | | Max media per post | 1 | | Text limit | 800 characters, title 100 | | Threads | No | | Quotes | No | | Remote delete | Yes | | Comments | No | | Likes | No | | Reposts | No | | Bookmarks | No | | Direct messages | No | | Post analytics | No | | Account analytics | No | Every pin is 1 image or video, saved to the board in `pinterest.boardId`. `text` is the description, and its first line is the default `title`. ## Connect [#connect] Connect in **Dashboard → Connections**, or with a [connect session](/docs/connection). The account needs a board. You can [create one](#boards) through the API. ### Permissions [#permissions] | Scope | Used for | | --- | --- | | `user_accounts:read` | Name, username and avatar | | `boards:read` | Listing boards | | `boards:write` | Creating boards | | `pins:read` | Reading pins and videos | | `pins:write` | Creating and deleting pins | ### Staying Connected [#staying-connected] Access renews itself, so `canAutoRenew` is `true`. [Reconnect](/docs/account-status#reconnect-an-account) if `status` leaves `active`, or on `TOKEN_INVALID`. Use the same Pinterest account, and its id stays the same. ## Publish [#publish] **TypeScript** ```typescript 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": "Ten ways to style open shelves in a small kitchen.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/kitchen-shelves.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_PINTEREST_ACCOUNT_ID", "pinterest": { "boardId": "1035968376946032411", "title": "Open Shelf Styling Ideas", "link": "https://example.com/blog/open-shelves" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Ten ways to style open shelves in a small kitchen.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/kitchen-shelves.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_PINTEREST_ACCOUNT_ID", "pinterest": { "boardId": "1035968376946032411", "title": "Open Shelf Styling Ideas", "link": "https://example.com/blog/open-shelves" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Ten ways to style open shelves in a small kitchen.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/kitchen-shelves.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_PINTEREST_ACCOUNT_ID", "pinterest": { "boardId": "1035968376946032411", "title": "Open Shelf Styling Ideas", "link": "https://example.com/blog/open-shelves" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_PINTEREST_ACCOUNT_ID", "platform": "pinterest", "source": "onepostly", "status": "publishing", "text": "Ten ways to style open shelves in a small kitchen.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/kitchen-shelves.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "pinterest": { "boardId": "1035968376946032411", "title": "Open Shelf Styling Ideas", "link": "https://example.com/blog/open-shelves" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` Once published, `platformPostId` is the pin id and `url` its pin link. ### Post Types [#post-types] | `mediaKind` | Publishes | Media | | --- | --- | --- | | `image` | Image pin | 1 image | | `video` | Video pin | 1 video, up to 64 MB | Other kinds, or more than 1 file, return `400 VALIDATION_ERROR`. A video pin is `published` once Pinterest processes it, so it takes longer. `coverImageUrl` sets its cover, and without it Pinterest picks a frame. ### Boards [#boards] [List Pinterest Boards](/docs/api-reference/pinterest/list-account-boards) returns up to 2,500 boards. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.listAccountBoards({ id: "acc_YOUR_PINTEREST_ACCOUNT_ID", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.list_account_boards( "acc_YOUR_PINTEREST_ACCOUNT_ID", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_PINTEREST_ACCOUNT_ID/boards" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "1035968376946032411", "name": "Recipes", "isDefault": true }, { "id": "1035968376946032398", "name": "Kitchen Ideas", "isDefault": false }, { "id": "1035968376946032405", "name": "Meal Prep", "isDefault": false } ] } ``` `isDefault` marks a suggested board. Pins only go there if you pass its `id`. [Create Pinterest Board](/docs/api-reference/pinterest/create-account-board) takes a `name` up to 180 characters and a `description` up to 500. The new `id` works as `boardId` right away. ### Options [#options] Options go under `pinterest`. Another platform's options there return `400`. | Field | Type | Description | | ------------------------------ | --------- | --------------------------------------------------------------- | | `accountId` (required) | `string` | The Pinterest account id. | | `text` | `string` | This account's text, up to 800 characters. | | `pinterest.boardId` (required) | `string` | The board to save the pin to. | | `pinterest.title` | `string` | The title, 1 to 100 characters. Default `First line of text`. | | `pinterest.description` | `string` | The description, up to 800 characters. Default `The post text`. | | `pinterest.link` | `string` | The URL the pin opens. See Destination Link. | | `pinterest.coverImageUrl` | `string` | Video pins only. A cover image URL. Default `A video frame`. | | `pinterest.isAiGenerated` | `boolean` | Adds the AI modified label. Default `false`. | `text` and `description` each stop at 800, so one cannot extend the other. #### Destination Link [#destination-link] `link` must be a full `https://` URL. `http://` and short links return `400`. Short links include `bit.ly`, `t.co` and `tinyurl.com`. Use the final URL. ### Media Requirements [#media-requirements] These are Pinterest's limits, on top of the [Media URL Requirements](/docs/media-uploads#media-url-requirements). #### Images [#images] | Property | Requirement | | --- | --- | | Formats | JPEG, PNG | | Max size | 20 MB | | Recommended | 1000 × 1500 (2:3) | #### Videos [#videos] | Property | Requirement | | --- | --- | | Formats | MP4, MOV, M4V | | Max size | 64 MB | | Min duration | 4 seconds | A video URL must send a `Content-Length` header. Uploaded files always do. ### Scheduling, Editing and Deleting [#scheduling-editing-and-deleting] [Scheduling and editing](/docs/scheduling) work as usual. Published pins return `NOT_EDITABLE`. [Deleting](/docs/post-lifecycle#delete-a-post) removes the pin. One already gone counts as deleted. ## Engagement [#engagement] Comments, likes, reposts and bookmarks return `UNSUPPORTED_PLATFORM`. ## Inbox [#inbox] Pinterest has no inbox through Onepostly. ## Analytics [#analytics] Pinterest reports no metrics here. A pin reads `pending` first, then `unsupported` for good. Account stats, insights, pin lists and sync return `UNSUPPORTED_PLATFORM`, so skip those calls for Pinterest. ## Limitations [#limitations] Not available for Pinterest through Onepostly. - Carousel pins - Text-only pins - Editing a published pin - Analytics and account stats - Listing or syncing outside pins - Comments, likes and messages ## Errors [#errors] Breaking a rule above returns `400 VALIDATION_ERROR` and creates nothing. Every code is in [Errors](/docs/error-handling). ### Publish Errors [#publish-errors] | Code | Cause | Fix | | --- | --- | --- | | `INVALID_MEDIA` | Video over 64 MB, or an empty file | Compress or fix the file | | `MEDIA_UNFETCHABLE` | No download, or no `Content-Length` | Upload the file instead | | `MEDIA_UPLOAD_FAILED` | Pinterest could not take the video | Check it plays, then post again | | `PUBLISH_FAILED` | Unknown board, or an image that failed | Read `error.message` | | `PERMISSION_DENIED` | Pinterest refused the action | Reconnect, or use your own board | | `NOT_EDITABLE` | An edit after publish | Delete and pin again | ### Board Errors [#board-errors] | Code | Cause | Fix | | --- | --- | --- | | `UNSUPPORTED_PLATFORM` | Not a Pinterest account | Use a Pinterest account | | `FORBIDDEN` | A `read_only` key creating a board | Use a `read_write` key | | `BOARDS_FAILED` | Boards did not load | Try again, then reconnect | | `BOARD_CREATE_FAILED` | Pinterest refused the board | Read the message | # Compare Platforms (/docs/platforms) Onepostly publishes to 9 platforms through one API. Check what each one accepts here, then open its page for options, media rules and errors. Every table comes from the data the API validates against. Bluesky connects with an [App Password](/docs/connection). Every other platform uses OAuth. ## Post Types [#post-types] | Platform | `text` | `image` | `multi_image` | `video` | `reel` | `document` | `stories` | Max files | | ---------------------------- | ------ | ------- | ------------- | --------------- | ------ | ---------- | --------- | --------- | | [X (Twitter)](/docs/x) | Yes | Yes | Yes | Yes | No | No | No | 4 | | [Instagram](/docs/instagram) | No | Yes | Yes | Yes (As a reel) | Yes | No | Yes | 10 | | [Facebook](/docs/facebook) | Yes | Yes | Yes | Yes | Yes | No | Yes | 10 | | [Threads](/docs/threads) | Yes | Yes | Yes | Yes | No | No | No | 20 | | [LinkedIn](/docs/linkedin) | Yes | Yes | Yes | Yes | No | Yes | No | 20 | | [YouTube](/docs/youtube) | No | No | No | Yes | No | No | No | 1 | | [TikTok](/docs/tiktok) | No | Yes | Yes | Yes | No | No | No | 35 | | [Pinterest](/docs/pinterest) | No | Yes | No | Yes | No | No | No | 1 | | [Bluesky](/docs/bluesky) | Yes | Yes | Yes | Yes | No | No | No | 4 | Instagram, YouTube, TikTok and Pinterest need media. Without `mediaKind`, the files decide the kind. Set it for `reel` and `stories`. See [Media Kinds](/docs/publishing#media-kinds). ## Text Limits [#text-limits] | Platform | Post text | `title` | `description` | `firstComment` | Comment or reply | Direct message | | ---------------------------- | --------- | ---------------- | ------------------- | -------------- | ---------------- | -------------- | | [X (Twitter)](/docs/x) | 280 | No | No | No | 280 | No | | [Instagram](/docs/instagram) | 2,200 | No | No | 2,200 | 2,200 | 1,000 | | [Facebook](/docs/facebook) | 63,206 | 100 (Reels) | No | 8,000 | 8,000 | 2,000 | | [Threads](/docs/threads) | 500 | No | No | 500 | 500 | No | | [LinkedIn](/docs/linkedin) | 3,000 | No | No | 1,250 | No | No | | [YouTube](/docs/youtube) | 5,000 | 100 | 5,000 | 10,000 | 10,000 | No | | [TikTok](/docs/tiktok) | 2,200 | 90 (photo posts) | 4,000 (photo posts) | No | No | No | | [Pinterest](/docs/pinterest) | 800 | 100 | 800 | No | No | No | | [Bluesky](/docs/bluesky) | 300 | No | No | No | 300 | 1,000 | | Counting | How it works | Platforms | | --- | --- | --- | | Characters | Each character counts as 1 | All except X and Bluesky | | Graphemes | Each visible character counts as 1, even a multi-part emoji | Bluesky | | Weighted | CJK and emoji count as 2, a URL as 23, the rest as 1 | X | - X allows 25,000 on accounts with a paid X subscription. Each X account has its own limit. See [X Subscriptions](/docs/x#x-subscriptions). - A TikTok photo post's title is cut from the post text, so it never fails. - A Facebook Reel's title is sent as `reelTitle`. - `No` means the platform has no such field, or Onepostly cannot send that text there. Every field is checked against each account when you create the post. Text that is too long returns `400 VALIDATION_ERROR` and nothing is created. A comment or message returns `400 TEXT_TOO_LONG` instead. ```json { "error": "Text is 312 characters (weighted). X allows 280. Shorten it or remove X.", "code": "VALIDATION_ERROR", "requestId": "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" } ``` To keep the account, give it a shorter `text` in [`accounts`](/docs/publishing#per-account-settings). ## Capabilities [#capabilities] ### Publishing and Analytics [#publishing-and-analytics] | Platform | Threads | Quotes | Remote delete | Post analytics | Account analytics | | ---------------------------- | ------- | ------ | ------------------------- | -------------- | ------------------------ | | [X (Twitter)](/docs/x) | Yes | Yes | Yes (Whole thread) | Yes | No | | [Instagram](/docs/instagram) | No | No | Yes (Facebook Login only) | Yes | Yes (Stats and insights) | | [Facebook](/docs/facebook) | No | No | Yes | Yes | Yes (Stats and insights) | | [Threads](/docs/threads) | Yes | Yes | Yes (Whole thread) | Yes | No | | [LinkedIn](/docs/linkedin) | No | No | Yes | No | No | | [YouTube](/docs/youtube) | No | No | Yes | Yes | No | | [TikTok](/docs/tiktok) | No | No | No | Yes | Yes (Stats) | | [Pinterest](/docs/pinterest) | No | No | Yes | No | No | | [Bluesky](/docs/bluesky) | Yes | Yes | Yes (Whole thread) | Yes | Yes (Stats) | ### Engagement [#engagement] | Platform | Comments | Likes | Reposts | Bookmarks | Direct messages | | ---------------------------- | -------- | ----- | ------- | --------- | --------------- | | [X (Twitter)](/docs/x) | Yes | Yes | Yes | Yes | No | | [Instagram](/docs/instagram) | Yes | No | No | No | Yes | | [Facebook](/docs/facebook) | Yes | Yes | No | No | Yes (Messenger) | | [Threads](/docs/threads) | Yes | No | Yes | No | No | | [LinkedIn](/docs/linkedin) | No | No | No | No | No | | [YouTube](/docs/youtube) | Yes | Yes | No | No | No | | [TikTok](/docs/tiktok) | No | No | No | No | No | | [Pinterest](/docs/pinterest) | No | No | No | No | No | | [Bluesky](/docs/bluesky) | Yes | Yes | Yes | Yes | Yes (Text only) | `No` means Onepostly cannot do it on that platform. Every platform supports [scheduling](/docs/scheduling). Remote delete works only on posts published through Onepostly. Others return `409 NOT_DELETABLE`. | Capability | Guide | | --- | --- | | Threads and quotes | [Threads, Replies and Quotes](/docs/replies-and-quotes) | | Remote delete | [Delete a Post](/docs/post-lifecycle#delete-a-post) | | Comments | [Comments](/docs/comments) | | Likes, reposts and bookmarks | [Likes and Reposts](/docs/engagement) | | Direct messages | [Inbox](/docs/inbox) | | Analytics | [Analytics](/docs/analytics) and [Account Insights](/docs/analytics#account-insights) | ## Choosing Platforms [#choosing-platforms] Breaking a rule returns `400 VALIDATION_ERROR` and creates nothing. | If your post | Keep in mind | | --- | --- | | Has no media | Instagram, YouTube, TikTok and Pinterest need media | | Has long text | Give X, Bluesky or Threads a shorter `text` of their own | | Has a `thread` | Every account must be on X, Threads or Bluesky | | Quotes a post | `quotePostId` works on X, Threads and Bluesky | | Replies to a post | `replyToPostId` works on Threads and Bluesky. On X, use [comments](/docs/comments) | | Goes to TikTok | Send `tiktok.privacyLevel` and its interaction choices. See [TikTok](/docs/tiktok#publish) | | Goes to Pinterest | Send `pinterest.boardId`. See [Pinterest](/docs/pinterest#publish) | | Goes to X | Each action is paid from your [wallet](/docs/pricing#x-wallet) | Platform pages share headings such as [Publish](/docs/x#publish), [Engagement](/docs/x#engagement) and [Analytics](/docs/x#analytics). # Threads (/docs/threads) Publish posts and reply chains, manage replies and reposts, and read metrics. ## Quick Reference [#quick-reference] | Property | Value | | ------------------ | --------------------------------------- | | Account types | Threads profiles | | Connection method | OAuth | | Post types | `text`, `image`, `multi_image`, `video` | | Max media per post | 20 | | Text limit | 500 characters | | Threads | Yes | | Quotes | Yes | | Remote delete | Yes (Whole thread) | | Comments | Yes | | Likes | No | | Reposts | Yes | | Bookmarks | No | | Direct messages | No | | Post analytics | Yes | | Account analytics | No | Each post, reply, `thread` item and `firstComment` has its own 500 limit. ## Connect [#connect] Connect a profile in **Dashboard → Connections**, or with a [connect session](/docs/connection). ### Permissions [#permissions] | Scope | Used for | | --- | --- | | `threads_basic` | Id, username and avatar | | `threads_content_publish` | Posts, replies, quotes and reposts | | `threads_read_replies` | Listing replies | | `threads_manage_replies` | Writing and hiding replies | | `threads_manage_insights` | Analytics | | `threads_delete` | Deleting posts and undoing reposts | ### Staying Connected [#staying-connected] Access lasts about 60 days and renews itself, so `canAutoRenew` is `true`. If it expires or the owner removes the app, you get `TOKEN_INVALID`. [Reconnect](/docs/account-status#reconnect-an-account) then, or on a `*_PERMISSION` code. The id stays the same. ## Publish [#publish] **TypeScript** ```typescript 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": "Launch week recap.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/launch-1.jpg" }, { "url": "https://cdn.onepostly.com/media/launch-2.jpg" }, { "url": "https://cdn.onepostly.com/media/launch-demo.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Launch week recap.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/launch-1.jpg" }, { "url": "https://cdn.onepostly.com/media/launch-2.jpg" }, { "url": "https://cdn.onepostly.com/media/launch-demo.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Launch week recap.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/launch-1.jpg" }, { "url": "https://cdn.onepostly.com/media/launch-2.jpg" }, { "url": "https://cdn.onepostly.com/media/launch-demo.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "source": "onepostly", "status": "publishing", "text": "Launch week recap.", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/launch-1.jpg" }, { "url": "https://cdn.onepostly.com/media/launch-2.jpg" }, { "url": "https://cdn.onepostly.com/media/launch-demo.mp4" } ], "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" } ] } ``` Once published, `platformPostId` is the Threads post id and `url` its link. ### Post Types [#post-types] | `mediaKind` | Publishes | Media | | --- | --- | --- | | `text` | Text post | None, `text` required | | `image` | Image post | 1 image | | `multi_image` | Carousel | 2 to 20 images or videos, mixed | | `video` | Video post | 1 video | `stories` returns `400 VALIDATION_ERROR`. Without `mediaKind`, the [files decide](/docs/publishing#media-kinds). A URL ending in `.mp4`, `.mov`, `.m4v`, `.webm` or `.avi` is a video. ### Threads [#threads] Add `thread` for 1 to 25 replies, each under the one before. The top-level `text` and `media` are the first post. See [Threads, Replies and Quotes](/docs/replies-and-quotes). | Rule | Detail | | --- | --- | | Reply text | Up to 500, empty only with media | | Reply media | 1 item, or a carousel of 2 to 20 | | Checked first | Every post and `firstComment`, before anything goes live | | Accounts | All on X, Threads or Bluesky | **TypeScript** ```typescript 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": "How we cut our build time in half.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/build-chart.png" } ], "thread": [ { "text": "1/ We cached dependencies between runs." }, { "text": "2/ Then we split tests across 4 machines.", "media": [ { "url": "https://cdn.onepostly.com/media/split-1.png" }, { "url": "https://cdn.onepostly.com/media/split-2.png" } ] } ], "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "How we cut our build time in half.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/build-chart.png" } ], "thread": [ { "text": "1/ We cached dependencies between runs." }, { "text": "2/ Then we split tests across 4 machines.", "media": [ { "url": "https://cdn.onepostly.com/media/split-1.png" }, { "url": "https://cdn.onepostly.com/media/split-2.png" } ] } ], "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "How we cut our build time in half.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/build-chart.png" } ], "thread": [ { "text": "1/ We cached dependencies between runs." }, { "text": "2/ Then we split tests across 4 machines.", "media": [ { "url": "https://cdn.onepostly.com/media/split-1.png" }, { "url": "https://cdn.onepostly.com/media/split-2.png" } ] } ], "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "source": "onepostly", "status": "publishing", "text": "How we cut our build time in half.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/build-chart.png" } ], "thread": [ { "text": "1/ We cached dependencies between runs.", "media": [] }, { "text": "2/ Then we split tests across 4 machines.", "media": [ { "url": "https://cdn.onepostly.com/media/split-1.png" }, { "url": "https://cdn.onepostly.com/media/split-2.png" } ] } ], "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" } ] } ``` `platformPostId` and `url` point to the first post. If a reply fails, earlier posts stay live and the post ends `failed`. ### Replies and Quotes [#replies-and-quotes] `threads.replyToPostId` replies to a post, and `threads.quotePostId` quotes one. Both take your `pst_` id or a Threads post id. With `thread`, the chain goes under the new reply, not under the post it replies to. **TypeScript** ```typescript 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": "This is the best explanation of rate limits I have read.", "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "threads": { "quotePostId": "18047312345678901" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "This is the best explanation of rate limits I have read.", "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "threads": { "quotePostId": "18047312345678901" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "This is the best explanation of rate limits I have read.", "accounts": [ { "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "threads": { "quotePostId": "18047312345678901" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "source": "onepostly", "status": "publishing", "text": "This is the best explanation of rate limits I have read.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": { "threads": { "quotePostId": "18047312345678901" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` A `pst_` id not live yet returns `409 POST_NOT_PUBLISHED`. These replies send post webhooks. [Comment](#comments) replies send `comment.created`. ### Options [#options] Options go under `threads`. Thread replies go in the top-level `thread`. | Field | Type | Description | | ----------------------- | -------- | ------------------------------------------------------ | | `accountId` (required) | `string` | The Threads account id. | | `text` | `string` | This account's text, up to 500 characters. | | `threads.replyToPostId` | `string` | The post to reply to, as a pst_ id or Threads id. | | `threads.quotePostId` | `string` | The post to quote, as a pst_ id or Threads id. | | `threads.firstComment` | `string` | A reply posted after publish, up to 500 characters. | | `threads.topicTag` | `string` | The first post's topic, 1 to 50 characters, no . or &. | #### Topic Tag [#topic-tag] `topicTag` replaces the topic Threads takes from a hashtag. It applies only to the first post, and is ignored on a reply. A tag with `.` or `&` fails with `INVALID_TOPIC_TAG`. #### First Comment [#first-comment] `firstComment` posts after the post and its `thread` replies go live. If Threads refuses it, the post still publishes. Deleting the post keeps it. ### Media Requirements [#media-requirements] These are Threads' limits, on top of the [Media URL Requirements](/docs/media-uploads#media-url-requirements). #### Images [#images] | Property | Requirement | | --- | --- | | Formats | JPEG, PNG | | Max size | 8 MB | | Width | 320 to 1440 | | Aspect ratio | Up to 10:1 | #### Videos [#videos] | Property | Requirement | | --- | --- | | Formats | MP4, MOV | | Codec | H.264 or HEVC, AAC | | Max size | 1 GB | | Duration | Up to 5 minutes | | Max width | 1920 | | Frame rate | 23 to 60 fps | | Aspect ratio | 9:16 recommended | ### Scheduling, Editing and Deleting [#scheduling-editing-and-deleting] [Scheduling and editing](/docs/scheduling) work as usual. Published posts cannot be edited. [Deleting](/docs/post-lifecycle#delete-a-post) removes the whole thread, replies first, but not `firstComment`. A partial delete returns `THREAD_DELETE_PARTIAL`, so send it again. Posts made outside Onepostly return `409 NOT_DELETABLE`. ### Threads Limits [#threads-limits] | Action | Per profile in 24 hours | | --- | --- | | Posts | 250 | | Replies | 1,000 | | Deletions | 100 | Past one, you get `QUOTA_EXCEEDED`. [Publishing limits](/docs/rate-limits#publishing-limits) apply too. ## Engagement [#engagement] See [Comments](/docs/comments) and [Likes and Reposts](/docs/engagement) for the requests. | Action | Supported | Notes | | --- | --- | --- | | List comments | Yes | Replies to the post, newest first | | Comment or reply | Yes | Up to 500 characters | | Delete a comment | Yes | Only the profile's own replies | | Hide or unhide | Yes | Replies under it follow it | | Repost | Yes | Any Threads post | | Undo a repost | Yes | See [Undo a Repost](#undo-a-repost) | | Quote | Yes | See [Replies and Quotes](#replies-and-quotes) | | Like, bookmark, list reposters | No | `UNSUPPORTED_PLATFORM` | | Like a comment, private reply | No | `UNSUPPORTED_PLATFORM` | Name a post by its `pst_` id or Threads id. Another account's `pst_` id returns `POST_ACCOUNT_MISMATCH`, so use the Threads id. ### Comments [#comments] On Threads, comments are replies, each with a `cmt_` id. The list skips replies to replies, so `parentId` is always `null` there. You cannot delete other people's replies, but you can hide them. ### Undo a Repost [#undo-a-repost] Threads undoes a repost only by the repost's own id. So it works only on reposts made here, of this profile's Onepostly posts. Others fail with `UNREPOST_REQUIRES_REPOST_ID`, so remove them in the Threads app. **TypeScript** ```typescript import { Configuration, EngagementApi } from "@onepostly/sdk"; const engagementApi = new EngagementApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await engagementApi.repostPost({ id: "acc_YOUR_THREADS_ACCOUNT_ID", postId: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.engagement_api import EngagementApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: engagement_api = EngagementApi(api_client) response = await engagement_api.repost_post( "acc_YOUR_THREADS_ACCOUNT_ID", "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X PUT "https://api.onepostly.com/v1/accounts/acc_YOUR_THREADS_ACCOUNT_ID/reposts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "reposted": true, "platformRepostId": "18062934718562044" } ``` ## Inbox [#inbox] Threads has no inbox through Onepostly. ## Analytics [#analytics] ### Metrics [#metrics] | Field | Threads metric | | --- | --- | | `impressions` | `views` | | `reach` | Always `null` | | `views` | `views` | | `likes` | `likes` | | `comments` | `replies` | | `shares` | `shares`, else `reposts` + `quotes` | | `saves` | Always `null` | | `engagement` | `likes` + `comments` + `shares` | A missing metric is `null`, not `0`. ### Read Post Analytics [#read-post-analytics] **TypeScript** ```typescript import { Configuration, AnalyticsApi } from "@onepostly/sdk"; const analyticsApi = new AnalyticsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await analyticsApi.getPostAnalytics({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.analytics_api import AnalyticsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: analytics_api = AnalyticsApi(api_client) response = await analytics_api.get_post_analytics( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/analytics" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "status": "ready", "metrics": { "impressions": 1234, "reach": null, "likes": 123, "comments": 12, "shares": 4, "saves": null, "views": 1234, "engagement": 139 }, "fetchedAt": "2027-03-15T10:00:00.000Z", "error": null } ``` Posts made outside work once [synced](/docs/publishing#posts-made-outside-onepostly). Freshness is the [standard](/docs/analytics#freshness). A fresh post reads `pending`. A deleted one reads `unavailable` with `POST_NOT_FOUND`. [List Account Media](/docs/api-reference/accounts/list-account-media) lists recent posts. Its `metrics` are `null`. ## Limitations [#limitations] Not available for Threads through Onepostly. - Editing a published post - Stories - Likes, bookmarks and reposter lists - Undoing reposts of outside posts - Replies to replies in the list - Liking replies and private replies - Direct messages - Account stats and insights ## Errors [#errors] A request that breaks a rule on this page returns `400 VALIDATION_ERROR` and creates nothing. Every code is in [Errors](/docs/error-handling). ### Publish Errors [#publish-errors] | Code | Cause | Fix | | --- | --- | --- | | `POST_NOT_PUBLISHED` | `409`. The `pst_` reply or quote target is not live | Wait, or use its Threads id | | `INVALID_MULTI_IMAGE` | Over 20 carousel items | Send 2 to 20 | | `INVALID_TOPIC_TAG` | `.` or `&` in `topicTag` | Remove them | | `CONTAINER_FAILED` | Threads could not process the media | See [Media Requirements](#media-requirements) | | `QUOTA_EXCEEDED` | A [Threads limit](#threads-limits) | Schedule it later | | `THREAD_DELETE_PARTIAL` | Some replies were not deleted | Send the delete again | | `DELETE_PERMISSION` | No `threads_delete` | Reconnect with every permission | ### Engagement Errors [#engagement-errors] | Code | Cause | Fix | | --- | --- | --- | | `POST_ACCOUNT_MISMATCH` | Another account's `pst_` id | Use the Threads id | | `UNREPOST_REQUIRES_REPOST_ID` | The repost was not made here | Remove it in the app | | `COMMENT_DELETE_FAILED` | Not the profile's own reply | Hide it instead | | `COMMENT_HIDE_FAILED` | The reply is gone, or not on the post | Check the reply | | `COMMENTS_UNSUPPORTED` | Replies cannot be listed | Check the post exists | ### Analytics Errors [#analytics-errors] | Code | Cause | Fix | | --- | --- | --- | | `ANALYTICS_PENDING` | No metrics yet | Read again later | | `POST_NOT_FOUND` | Deleted on Threads | Check the post | | `ANALYTICS_PERMISSION` | No `threads_manage_insights` | Reconnect with every permission | # TikTok (/docs/tiktok) Publish videos and photo posts, and read post metrics and account stats. ## Quick Reference [#quick-reference] | Property | Value | | ------------------ | ------------------------------------------------------------------------- | | Account types | TikTok accounts | | Connection method | OAuth | | Post types | `video`, `image`, `multi_image` | | Max media per post | 35 | | Text limit | 2,200 characters, title 90 (photo posts), description 4,000 (photo posts) | | Threads | No | | Quotes | No | | Remote delete | No | | Comments | No | | Likes | No | | Reposts | No | | Bookmarks | No | | Direct messages | No | | Post analytics | Yes | | Account analytics | Yes (Stats) | A post needs [uploaded media](/docs/media-uploads), a `privacyLevel` and each [interaction](#interactions) choice. > TikTok takes only files uploaded with Create Media. Any other media URL fails with `INVALID_MEDIA`, so upload the file first. ## Connect [#connect] Connect in **Dashboard → Connections**, or with a [connect session](/docs/connection). ### Permissions [#permissions] | Scope | Used for | |---|---| | `user.info.basic` | User id, name and avatar | | `user.info.profile` | Username, for post links | | `user.info.stats` | Account stats | | `video.list` | Analytics, video list and sync | | `video.publish` | Publishing | A missing scope returns `PERMISSION_DENIED` or `ANALYTICS_PERMISSION`. Reconnect the account and approve every permission. ### Staying Connected [#staying-connected] Access renews itself, so `canAutoRenew` is `true`. It ends if the creator revokes it in TikTok, and you then get `TOKEN_INVALID`. [Reconnect](/docs/account-status#reconnect-an-account) with the same TikTok account. The id stays the same. ## Publish [#publish] **TypeScript** ```typescript 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": "Behind the scenes of launch day #startup", "mediaKind": "video", "media": [ { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" } ], "accounts": [ { "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": true, "allowStitch": true } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Behind the scenes of launch day #startup", "mediaKind": "video", "media": [ { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" } ], "accounts": [ { "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": true, "allowStitch": true } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Behind the scenes of launch day #startup", "mediaKind": "video", "media": [ { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" } ], "accounts": [ { "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": true, "allowStitch": true } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "platform": "tiktok", "source": "onepostly", "status": "publishing", "text": "Behind the scenes of launch day #startup", "mediaKind": "video", "media": [ { "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a0b.mp4" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": true, "allowStitch": true } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` The post stays `publishing` while TikTok processes it. ### Post Types [#post-types] | `mediaKind` | Publishes | Media | |---|---|---| | `video` | Video post | 1 video | | `image` | Photo post | 1 photo | | `multi_image` | Photo carousel | 2 to 35 photos | A post has one video or photos, never both. `text` and `stories` return `400`. ### Text and Captions [#text-and-captions] | Post | Caption | Title | |---|---|---| | Video | `text`, up to 2,200 | None | | Photo | `tiktok.description`, up to 4,000, else `text` | First 90 of `text` | The title is cut at 90, so long `text` is not refused. ### Photo Posts [#photo-posts] `photoCoverIndex` picks the cover photo, counting from `0`. `autoAddMusic` adds TikTok's suggested music to the post. **TypeScript** ```typescript 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": "Weekend on the coast", "mediaKind": "multi_image", "media": [ { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a03" }, { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a04" }, { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a05" } ], "accounts": [ { "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "tiktok": { "description": "Two days, three beaches, one very windy picnic. #travel #roadtrip", "privacyLevel": "public_to_everyone", "allowComment": false, "photoCoverIndex": 1, "autoAddMusic": true } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Weekend on the coast", "mediaKind": "multi_image", "media": [ { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a03" }, { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a04" }, { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a05" } ], "accounts": [ { "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "tiktok": { "description": "Two days, three beaches, one very windy picnic. #travel #roadtrip", "privacyLevel": "public_to_everyone", "allowComment": false, "photoCoverIndex": 1, "autoAddMusic": true } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Weekend on the coast", "mediaKind": "multi_image", "media": [ { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a03" }, { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a04" }, { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a05" } ], "accounts": [ { "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "tiktok": { "description": "Two days, three beaches, one very windy picnic. #travel #roadtrip", "privacyLevel": "public_to_everyone", "allowComment": false, "photoCoverIndex": 1, "autoAddMusic": true } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "platform": "tiktok", "source": "onepostly", "status": "publishing", "text": "Weekend on the coast", "mediaKind": "multi_image", "media": [ { "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a03.jpg" }, { "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a04.jpg" }, { "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a05.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "tiktok": { "description": "Two days, three beaches, one very windy picnic. #travel #roadtrip", "privacyLevel": "public_to_everyone", "allowComment": false, "photoCoverIndex": 1, "autoAddMusic": true } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` ### Privacy Levels [#privacy-levels] Every TikTok account needs `tiktok.privacyLevel`. | Value | Who can see it | |---|---| | `public_to_everyone` | Everyone | | `mutual_follow_friends` | Followers the creator follows back | | `follower_of_creator` | Followers | | `self_only` | Only the creator | The creator's settings decide which values work. Others return `400 INVALID_PRIVACY_LEVEL`. The level is checked again at publish, so a privacy change in TikTok can fail a scheduled post that passed on create. Only `public_to_everyone` posts get a post id, a link and metrics. #### Creator Info [#creator-info] TikTok asks you to read and show the creator's settings before each post. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.getCreatorInfo({ id: "acc_YOUR_TIKTOK_ACCOUNT_ID", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.get_creator_info( "acc_YOUR_TIKTOK_ACCOUNT_ID", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_TIKTOK_ACCOUNT_ID/creator-info" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "username": "yourbrand", "nickname": "Your Brand", "avatarUrl": "https://p16-sign-va.tiktokcdn.com/tos-maliva-avt-0068/7310942817465028614~c5_168x168.jpeg", "privacyLevelOptions": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "commentDisabled": false, "duetDisabled": false, "stitchDisabled": false, "maxVideoPostDurationSec": 600, "fetchedAt": "2027-03-15T08:59:30.000Z" } ``` | Field | Meaning | |---|---| | `privacyLevelOptions` | Allowed `privacyLevel` values | | `commentDisabled` | Comments are off in TikTok | | `duetDisabled` | Duets are off, such as on a private account | | `stitchDisabled` | Stitches are off, such as on a private account | | `maxVideoPostDurationSec` | The longest video allowed, or `null` | These settings are read live. Creating or editing a post reads them too, and the request fails if they cannot be loaded. ### Interactions [#interactions] TikTok wants the creator to pick every interaction, so each post sets them. | Option | Applies to | Required | |---|---|---| | `tiktok.allowComment` | Videos and photos | Yes | | `tiktok.allowDuet` | Videos only | On videos | | `tiktok.allowStitch` | Videos only | On videos | - A missing one returns `400 VALIDATION_ERROR`. On photos, duet or stitch returns `400`. - `true` for an interaction the creator turned off returns `400 INTERACTION_DISABLED`. - If the creator turns one off after scheduling, the post publishes with it off. ### Post ID and Link [#post-id-and-link] | Field | Once public | Before that, or not public | |---|---|---| | `platformPostId` | The TikTok post id | A publish id, `v_pub_…` or `p_pub_…` | | `url` | The post link | The profile for videos, `null` for photos | A public post can be `published` before TikTok's review ends. Once public, both fields update and `post.updated` fires, so store the new values. ### Options [#options] Options go under `tiktok`. Another platform's options there return `400`. | Field | Type | Description | | -------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | | `accountId` (required) | `string` | The TikTok account id. | | `text` | `string` | This account's text, up to 2,200 characters. | | `tiktok.privacyLevel` (required) | `"public_to_everyone" \| "mutual_follow_friends" \| "follower_of_creator" \| "self_only"` | Who can see it. See Privacy Levels. | | `tiktok.allowComment` (required) | `boolean` | Lets viewers comment. | | `tiktok.allowDuet` | `boolean` | Videos only, and required there. Lets viewers duet. | | `tiktok.allowStitch` | `boolean` | Videos only, and required there. Lets viewers stitch. | | `tiktok.brandOrganicToggle` | `boolean` | Labels it as promoting the creator's own business. Default `false`. | | `tiktok.brandContentToggle` | `boolean` | Labels it as a paid partnership. Default `false`. | | `tiktok.isAiGenerated` | `boolean` | Adds the AI-generated label. Default `false`. | | `tiktok.description` | `string` | Photos only. The caption, up to 4,000 characters. Default `The post text`. | | `tiktok.videoCoverTimestampMs` | `integer` | Videos only. The cover frame, up to 600,000 ms. Default `1000`. | | `tiktok.photoCoverIndex` | `integer` | Photos only. The cover photo, from 0 to 34. Default `0`. | | `tiktok.autoAddMusic` | `boolean` | Photos only. Adds suggested music. Default `false`. | #### Disclosure Labels [#disclosure-labels] You can set both brand labels. A paid partnership cannot be `self_only`. That combination passes on create but fails at publish. ### Media Requirements [#media-requirements] #### Images [#images] | Property | Requirement | |---|---| | Formats | JPEG, WebP, not PNG or GIF | | Max size | 20 MB | | Max resolution | 1080p | #### Videos [#videos] | Property | Requirement | |---|---| | Formats | MP4, MOV, WebM | | Max size | 1 GB | | Duration | Up to `maxVideoPostDurationSec` | | Frame rate | 23 to 60 fps | | Dimensions | 360 to 4096 each side | ### Scheduling, Editing and Deleting [#scheduling-editing-and-deleting] [Scheduling and editing](/docs/scheduling) work as usual. Both check the creator's settings. A post that is publishing or published returns `NOT_EDITABLE`. You can cancel a post before publish. During processing, a delete returns `POST_PUBLISHING`. Published posts can only be deleted in the TikTok app. ## Engagement [#engagement] TikTok has no comments, likes, reposts or bookmarks here. Those calls return `UNSUPPORTED_PLATFORM`. Counts are in [analytics](#analytics). ## Inbox [#inbox] TikTok has no inbox through Onepostly. ## Analytics [#analytics] ### Metrics [#metrics] | Field | TikTok metric | |---|---| | `impressions` | `view_count` | | `reach` | Always `null` | | `views` | `view_count` | | `likes` | `like_count` | | `comments` | `comment_count` | | `shares` | `share_count` | | `saves` | Always `null` | | `engagement` | `likes` + `comments` + `shares` | Only `public_to_everyone` posts have metrics. Freshness is the [standard](/docs/analytics#freshness). | Status | Code | Meaning | |---|---|---| | `pending` | `VIDEO_ID_PENDING` | Not public yet, read again later | | `pending` | `VIDEO_NOT_FOUND` | Public, but no metrics yet | | `unavailable` | `PRIVACY_RESTRICTED` | Not public, for good | On YouTube, `VIDEO_NOT_FOUND` means gone for good. Read it with `status`. ### Account Stats [#account-stats] [Get Account Stats](/docs/api-reference/accounts/get-account-stats) reads followers, following, likes and videos live. `likesCount` counts likes across all of the creator's videos. ### Recent Posts [#recent-posts] [List Account Media](/docs/api-reference/accounts/list-account-media) lists public videos with metrics, 20 per page. The first page adds your non-public posts, with a publish id and `null` metrics. ## Limitations [#limitations] Not available for TikTok through Onepostly. - Text posts and stories - Mixing photos and a video - Editing or deleting published posts - Comments, likes, reposts and bookmarks - Quotes and reply chains - Direct messages - Sending to drafts - Metrics for non-public posts ## Errors [#errors] Breaking a rule on this page returns `400 VALIDATION_ERROR` and creates nothing. TikTok can also refuse a setting at publish and fail the post. Every code is in [Errors](/docs/error-handling). ### Publish Errors [#publish-errors] | Code | Cause | Fix | |---|---|---| | `INVALID_PRIVACY_LEVEL` | Not in `privacyLevelOptions` | Use an allowed value | | `INTERACTION_DISABLED` | `true` for an interaction the creator turned off | Send `false` | | `INVALID_MEDIA` | A file not uploaded with Create Media | Upload it first | | `URL_OWNERSHIP_UNVERIFIED` | TikTok refused the file | Upload it again | | `CREATOR_INFO_FAILED` | `502`. Creator info did not load | Try again, then reconnect | | `MEDIA_UPLOAD_FAILED` | TikTok refused to start the post | Read `error.message` | | `MEDIA_PROCESSING_TIMEOUT` | Processing took too long | Check the profile first | | `SPAM_RISK` | TikTok flagged the post | Change the caption and media | | `POSTING_LIMIT_REACHED` | Too many recent posts | Wait before posting | | `ACCOUNT_RESTRICTED` | TikTok restricted posting | Fix it in the app | | `CAPACITY_LIMITED` | TikTok is not taking direct posts | Try again in a few hours | | `UNSUPPORTED_PLATFORM` | A delete of a published post | Delete it in the app | ### Analytics Errors [#analytics-errors] | Code | Cause | Fix | |---|---|---| | `VIDEO_ID_PENDING` | Not public yet | Read again later | | `VIDEO_NOT_FOUND` | No metrics yet | Read again later | | `PRIVACY_RESTRICTED` | Not public | Publish to everyone | | `ANALYTICS_PERMISSION` | No `video.list` | Reconnect with every permission | | `STATS_FAILED` | Stats did not load | Try again later | # X (Twitter) (/docs/x) Publish posts and threads, engage and read metrics, all paid from your wallet. ## Quick Reference [#quick-reference] | Property | Value | | ------------------ | --------------------------------------------------------------- | | Account types | Any X account | | Connection method | OAuth | | Post types | `text`, `image`, `multi_image`, `video` | | Max media per post | 4 | | Text limit | 280 characters (weighted), or 25,000 with a paid X subscription | | Threads | Yes | | Quotes | Yes | | Remote delete | Yes (Whole thread) | | Comments | Yes | | Likes | Yes | | Reposts | Yes | | Bookmarks | Yes | | Direct messages | No | | Post analytics | Yes | | Account analytics | No | X weighs text. CJK and emoji count as 2, a URL as 23, the rest as 1. Each account has its own limit, see [X Subscriptions](#x-subscriptions). ### X Wallet [#x-wallet] X charges for every API call, so X actions are paid from your prepaid wallet. Posting to any other platform never touches the wallet. | Action | Price | | --- | --- | | Post, reply or quote | $0.015, or $0.20 with a URL | | Like, repost or bookmark | $0.015 | | Undo, or delete one post | $0.01 | | Post analytics | $0.005 per post, once per UTC day | | List replies or reposters | $0.005 per page | Each thread post is charged on its own. A low balance returns `402 INSUFFICIENT_WALLET` and changes nothing. A call X fails is not charged. The owner tops up under **Settings → Wallet**. See [X Prices](/docs/pricing#x-prices) and [X Wallet](/docs/pricing#x-wallet). ## Connect [#connect] Any X account works. Connect it in **Dashboard → Connections**, or with a connect session for `platform: "x"`. See [Connect Accounts](/docs/connection). **TypeScript** ```typescript import { Configuration, ConnectApi } from "@onepostly/sdk"; const connectApi = new ConnectApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await connectApi.createConnectSession({ createConnectSessionBody: { "platform": "x", "redirectUrl": "https://app.example.com/onepostly/connected" }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.connect_api import ConnectApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: connect_api = ConnectApi(api_client) response = await connect_api.create_connect_session( create_connect_session_body={ "platform": "x", "redirectUrl": "https://app.example.com/onepostly/connected" }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/connect-sessions" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "platform": "x", "redirectUrl": "https://app.example.com/onepostly/connected" }' ``` **Response** ```json { "url": "https://x.com/i/oauth2/authorize?response_type=code&client_id=bTJ4ZFhfY2xpZW50&scope=tweet.read%20tweet.write%20users.read%20media.write%20like.read%20like.write%20bookmark.read%20bookmark.write%20offline.access&state=st_9Kq2mXv7Lp&code_challenge=Yk3q9dW2nR8vL5xT0aZ7cB4mF1hJ6sP3uE8gN2kQ5wA&code_challenge_method=S256", "expiresAt": "2027-03-01T10:05:00.000Z" } ``` The browser returns to `redirectUrl` with the `accountId`. Each X account also has `xSubscriptionType`, which sets its [text limit](#x-subscriptions). ### Permissions [#permissions] | Scope | Used for | | --- | --- | | `tweet.read` | Reading posts, replies, reposters and metrics | | `tweet.write` | Posting, replying, quoting, reposting and deleting | | `users.read` | Name, handle, avatar and subscription | | `media.write` | Uploading images, GIFs and videos | | `like.read`, `like.write` | Likes | | `bookmark.read`, `bookmark.write` | Bookmarks | | `offline.access` | Staying connected without a new sign-in | ### Staying Connected [#staying-connected] X access renews itself, so `canAutoRenew` is `true`. Access ends when the owner revokes the app or changes the account password. | What happens | What you see | What to do | | --- | --- | --- | | X rejects access on a publish | The post fails with `TOKEN_EXPIRED` | Retry, then reconnect if it repeats | | Access can no longer renew | `status` leaves `active`, posts fail with `TOKEN_INVALID` | Reconnect | | You publish to an inactive account | `409 CONNECTION_INACTIVE` | Reconnect | A [reconnect](/docs/account-status#reconnect-an-account) keeps the account id, so scheduled posts keep working. ## Publish [#publish] **TypeScript** ```typescript 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": "Version 2.4 is live. Faster sync and a new dashboard.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Version 2.4 is live. Faster sync and a new dashboard.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Version 2.4 is live. Faster sync and a new dashboard.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "Version 2.4 is live. Faster sync and a new dashboard.", "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" } ] } ``` Once published, `platformPostId` is the numeric X post id and `url` its `x.com` link. See [Post Status](/docs/post-lifecycle#post-status) for every status a post can have. ### Post Types [#post-types] | `mediaKind` | Media | | --- | --- | | `text` | None, `text` required | | `image` | 1 image or 1 GIF | | `multi_image` | 2 to 4 images, no GIF or video | | `video` | 1 video | `stories` returns `400 VALIDATION_ERROR`. Without `mediaKind`, the [files decide](/docs/publishing#media-kinds). A GIF always goes alone, as `image`. A GIF mixed with other media passes when you create the post but fails at publish. ### Threads [#threads] Add `thread` for 1 to 25 replies after the first post. The top-level `text` and `media` are the first post. See [Threads, Replies and Quotes](/docs/replies-and-quotes). | Rule | Detail | | --- | --- | | Reply text | Empty only with media. Same limit as a post | | Reply media | Up to 4 images, or 1 video or GIF | | Checked first | All text and media, before anything goes live | | Price | Each post is charged | **TypeScript** ```typescript 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": "How to ship your first integration in 3 steps.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/cover.jpg" } ], "thread": [ { "text": "1/ Create an API key in the dashboard." }, { "text": "2/ Connect your X account.", "media": [ { "url": "https://cdn.onepostly.com/media/connect.jpg" } ] }, { "text": "3/ Send your first post." } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "How to ship your first integration in 3 steps.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/cover.jpg" } ], "thread": [ { "text": "1/ Create an API key in the dashboard." }, { "text": "2/ Connect your X account.", "media": [ { "url": "https://cdn.onepostly.com/media/connect.jpg" } ] }, { "text": "3/ Send your first post." } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "How to ship your first integration in 3 steps.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/cover.jpg" } ], "thread": [ { "text": "1/ Create an API key in the dashboard." }, { "text": "2/ Connect your X account.", "media": [ { "url": "https://cdn.onepostly.com/media/connect.jpg" } ] }, { "text": "3/ Send your first post." } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID" } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "How to ship your first integration in 3 steps.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/cover.jpg" } ], "thread": [ { "text": "1/ Create an API key in the dashboard.", "media": [] }, { "text": "2/ Connect your X account.", "media": [ { "url": "https://cdn.onepostly.com/media/connect.jpg" } ] }, { "text": "3/ Send your first post.", "media": [] } ], "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" } ] } ``` `platformPostId` and `url` point to the first post. If a reply fails, the live posts stay and the post ends `failed`. [Deleting](#scheduling-editing-and-deleting) removes them. ### Replies and Quotes [#replies-and-quotes] `x.quotePostId` quotes the `pst_` id of your X post, or any numeric X id. **TypeScript** ```typescript 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": "Worth reading if you run scheduled jobs.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "quotePostId": "1960956321831854280" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Worth reading if you run scheduled jobs.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "quotePostId": "1960956321831854280" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Worth reading if you run scheduled jobs.", "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "quotePostId": "1960956321831854280" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "Worth reading if you run scheduled jobs.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": { "x": { "quotePostId": "1960956321831854280" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` A `pst_` id from another platform returns `400 VALIDATION_ERROR`. One not yet live returns `409 POST_NOT_PUBLISHED`. X has no `replyToPostId`. Reply with the [comment endpoints](#comments). ### Options [#options] X options go under `x` in each `accounts` entry. | Field | Type | Description | | ---------------------- | ---------- | ------------------------------------------------------------------- | | `accountId` (required) | `string` | The X account id. | | `text` | `string` | This account's text, in place of the top-level text. | | `x.quotePostId` | `string` | The post to quote, as a pst_ id or a numeric X id. | | `x.geoRestriction` | `string[]` | 1 to 25 uppercase country codes, such as ["US", "ES"]. Needs media. | #### Geo Restriction [#geo-restriction] `x.geoRestriction` shows the media only in the listed countries, while the text stays visible. It covers every thread post with media. Without any media, you get `400 VALIDATION_ERROR`. If X rejects the list, the post fails with `GEO_RESTRICTION_FAILED`. **TypeScript** ```typescript 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": "Spring sale, available in the US and Spain.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/sale.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "geoRestriction": [ "US", "ES" ] } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Spring sale, available in the US and Spain.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/sale.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "geoRestriction": [ "US", "ES" ] } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Spring sale, available in the US and Spain.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/sale.jpg" } ], "accounts": [ { "accountId": "acc_YOUR_X_ACCOUNT_ID", "x": { "geoRestriction": [ "US", "ES" ] } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "Spring sale, available in the US and Spain.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/sale.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "x": { "geoRestriction": [ "US", "ES" ] } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` #### X Subscriptions [#x-subscriptions] A paid X subscription raises the limit from 280 to 25,000 in posts, thread replies and comments. `xSubscriptionType` on the account is `None`, `Basic`, `Premium` or `PremiumPlus`, and anything but `None` gets 25,000. A change can take a few hours, or apply now with a reconnect. Each account is checked alone, so one text can pass on one account and fail on another. If the subscription ends before publish, the post fails with `TEXT_TOO_LONG`. ### Media Requirements [#media-requirements] These are X's limits, on top of the [Media URL Requirements](/docs/media-uploads#media-url-requirements). #### Images [#images] | Property | Requirement | | --- | --- | | Formats | JPEG, PNG, WebP | | Max size | 5 MB | | Per post | 1 (`image`) or 2 to 4 (`multi_image`) | | Recommended | 1200 × 675 (16:9), 1200 × 1200 (1:1) or 1080 × 1350 (4:5) | #### GIFs [#gifs] | Property | Requirement | | --- | --- | | Max size | 15 MB | | Max dimensions | 1280 × 1080 | | Per post | 1, alone | #### Videos [#videos] | Property | Requirement | | --- | --- | | Formats | MP4 or MOV (H.264, AAC) | | Max size | 512 MB | | Duration | 0.5 to 140 seconds | | Per post | 1, alone | | Recommended | 1280 × 720, 30 fps | The content type, then the extension, marks a file as a video, GIF or image. ### Scheduling, Editing and Deleting [#scheduling-editing-and-deleting] [Scheduling](/docs/scheduling) works as on any platform. The balance must cover the post on create, and is charged at publish. An edit that changes the text or thread is checked again. Published posts cannot be edited. [Deleting](/docs/post-lifecycle#delete-a-post) a published post removes its whole thread, replies first, and is charged per post. A post already gone on X counts as deleted. A partial delete returns `THREAD_DELETE_PARTIAL`, so send it again. Posts made outside Onepostly return `409 NOT_DELETABLE`. ## Engagement [#engagement] Every action is paid from your wallet. See [Comments](/docs/comments) and [Likes and Reposts](/docs/engagement). | Action | Supported | Notes | | --- | --- | --- | | List comments | Yes | Last 7 days, charged per page | | Comment or reply | Yes | Posted as a reply | | Delete a comment | Yes | The account's own replies | | Hide or like a comment | No | | | Private reply | No | | | Like, repost, bookmark | Yes | Any post. Bookmarks are private | | List reposters | Yes | Your posts, charged per page | | Quote | Yes | See [Replies and Quotes](#replies-and-quotes) | Name a post by its `pst_` id or its numeric X id. The X id works for any post. Another account's `pst_` id returns `POST_ACCOUNT_MISMATCH`. ### Comments [#comments] On X, comments are replies, each with a `cmt_` id. | Action | On X | | --- | --- | | List | Replies from the last 7 days, X's search window, without the post itself | | Comment | A reply to the post, with a post's limit and price | | Reply | A reply to a reply | | Delete | The account's own reply. Your own post returns `NOT_A_COMMENT` | **TypeScript** ```typescript import { Configuration, CommentsApi } from "@onepostly/sdk"; const commentsApi = new CommentsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await commentsApi.createComment({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", commentTextBody: { "text": "Thanks for the feedback, the fix ships Friday." }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.comments_api import CommentsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: comments_api = CommentsApi(api_client) response = await comments_api.create_comment( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", comment_text_body={ "text": "Thanks for the feedback, the fix ships Friday." }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/comments" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Thanks for the feedback, the fix ships Friday." }' ``` **Response** ```json { "id": "cmt_6Hq2ZtW9xLmB4vRk8NpD3sYc7GfJ1aUe5TnQ0oKiXwVb2MzCr6PyLd9EhSj4AgFu8RtNk3WqZm7Yx1BvC5Ls0DpHi2OeJn6Ua9Kf4Tw", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "platformCommentId": "1900934567890123456", "parentId": null, "text": "Thanks for the feedback, the fix ships Friday.", "username": null, "likeCount": 0, "createdAt": "2027-03-15T10:00:00.000Z", "replies": [] } ``` ### Likes, Reposts and Bookmarks [#likes-reposts-and-bookmarks] Undo each with `DELETE` on the same path. For a repost, that path names the original post, so there is no repost id to track. **TypeScript** ```typescript import { Configuration, EngagementApi } from "@onepostly/sdk"; const engagementApi = new EngagementApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await engagementApi.likePost({ id: "acc_YOUR_X_ACCOUNT_ID", postId: "1960956321831854280", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.engagement_api import EngagementApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: engagement_api = EngagementApi(api_client) response = await engagement_api.like_post( "acc_YOUR_X_ACCOUNT_ID", "1960956321831854280", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X PUT "https://api.onepostly.com/v1/accounts/acc_YOUR_X_ACCOUNT_ID/likes/1960956321831854280" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "liked": true } ``` ## Inbox [#inbox] X has no inbox through Onepostly. ## Analytics [#analytics] Read metrics for any X post you published or [synced](/docs/publishing#posts-made-outside-onepostly). ### Metrics [#metrics] | Field | X metric | | --- | --- | | `impressions` | Impressions | | `reach` | Always `null` | | `views` | Impressions | | `likes` | Likes | | `comments` | Replies | | `shares` | Reposts plus quotes | | `saves` | Bookmarks | | `engagement` | `likes` + `comments` + `shares` + `saves` | X gives detailed counts to the author only, for 30 days. After that, you get the public counts. A missing value is `null`. ### Read Post Analytics [#read-post-analytics] **TypeScript** ```typescript import { Configuration, AnalyticsApi } from "@onepostly/sdk"; const analyticsApi = new AnalyticsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await analyticsApi.getPostAnalytics({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.analytics_api import AnalyticsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: analytics_api = AnalyticsApi(api_client) response = await analytics_api.get_post_analytics( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/analytics" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "status": "ready", "metrics": { "impressions": 1234, "reach": null, "likes": 123, "comments": 12, "shares": 4, "saves": 2, "views": 1234, "engagement": 141 }, "fetchedAt": null, "error": null } ``` X has no daily timeline, so the [timeline](/docs/api-reference/analytics/get-post-analytics-timeline) returns `TIMELINE_UNSUPPORTED`. ### Freshness [#freshness] X metrics are read live when you call, at most once per post per UTC day. `fetchedAt` is always `null`. See [Freshness](/docs/analytics#freshness). | Read | Charge | | --- | --- | | First read of the UTC day | The analytics price | | Later reads that day | Free, same numbers | | A read with no metrics | Free, the next call reads again | | A due read the wallet cannot cover | `402 INSUFFICIENT_WALLET`. Posts already read today still answer | ### Recent Posts [#recent-posts] [List Account Media](/docs/api-reference/accounts/list-account-media) lists the account's recent image and video posts, newest first, with metrics. It includes reposts, skips replies, and is free. **TypeScript** ```typescript import { Configuration, AccountsApi } from "@onepostly/sdk"; const accountsApi = new AccountsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await accountsApi.listAccountMedia({ id: "acc_YOUR_X_ACCOUNT_ID", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.accounts_api import AccountsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: accounts_api = AccountsApi(api_client) response = await accounts_api.list_account_media( "acc_YOUR_X_ACCOUNT_ID", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/accounts/acc_YOUR_X_ACCOUNT_ID/media" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "data": [ { "id": "1900912345678901234", "title": "Watch the 90-second walkthrough. https://t.co/Xk4p9QmZ2v", "description": "Watch the 90-second walkthrough. https://t.co/Xk4p9QmZ2v", "coverUrl": "https://pbs.twimg.com/amplify_video_thumb/1900912345678901234/img/Qm3nX8kP2rT5vW7y.jpg", "url": "https://x.com/yourbrand/status/1900912345678901234", "createdAt": "2027-03-14T16:30:12.000Z", "durationSec": 90, "metrics": { "likes": 86, "comments": 9, "shares": 14, "views": 5210 } }, { "id": "1900893456789012345", "title": "Ship day in 4 frames. https://t.co/Rb7nL2wQ8s", "description": "Ship day in 4 frames. https://t.co/Rb7nL2wQ8s", "coverUrl": "https://pbs.twimg.com/media/GkT3bQxWcAAz9Lp.jpg", "url": "https://x.com/yourbrand/status/1900893456789012345", "createdAt": "2027-03-14T11:05:47.000Z", "durationSec": null, "metrics": { "likes": 42, "comments": 3, "shares": 5, "views": 2318 } } ], "nextCursor": "7140dibdnow9c7btw4b0ld1ak2pzz6c1c2zuh0xb5c9yd", "hasMore": true } ``` A post deleted on X, or hidden from the account, reads `unavailable` with `POST_NOT_FOUND`. See [Analytics Status](/docs/analytics#analytics-status) for the other statuses. ## Limitations [#limitations] Not available for X through Onepostly. - Polls - Editing a published post - `replyToPostId`. Use comments instead - Choosing who can reply - Hiding or liking replies - Direct messages - Account stats and insights - Daily analytics timelines - Stories ## Errors [#errors] Breaking a rule on this page returns `400 VALIDATION_ERROR` and creates nothing. X's own media limits are checked at publish, and fail the post with `INVALID_MEDIA`. Every code is in [Errors](/docs/error-handling). ### Publish Errors [#publish-errors] | Code | Cause | Fix | | --- | --- | --- | | `POST_NOT_PUBLISHED` | `409`. The quoted `pst_` post is not live | Wait, or use its X id | | `NOT_DELETABLE` | `409`. A post made outside Onepostly | Delete it in the X app | | `TEXT_TOO_LONG` | Over the account's limit at publish | Shorten the text | | `INVALID_MEDIA` | Too many files, mixed video, empty or too large | See [Media Requirements](#media-requirements) | | `MEDIA_PROCESSING_FAILED` | X could not process the media | Re-encode the file | | `MEDIA_PROCESSING_TIMEOUT` | X took too long | Use a smaller or shorter file | | `GEO_RESTRICTION_FAILED` | X rejected the country list | Fix the codes, or drop them | | `DUPLICATE_CONTENT` | X saw the text as a duplicate | Change the text | | `ACCOUNT_RESTRICTED` | Suspended, locked or read-only | Fix it in the X app | | `RATE_LIMITED` | X throttled the account, or a [publishing limit](/docs/rate-limits#publishing-limits) | Post again later | | `INSUFFICIENT_WALLET` | `402` on create, edit or delete, or a scheduled post the wallet no longer covers | [Top up](/docs/pricing#top-up) | | `THREAD_DELETE_PARTIAL` | Some replies were not deleted | Send the delete again | | `PUBLISH_FAILED` | X rejected the post | Read `error.message` | ### Engagement Errors [#engagement-errors] | Code | Cause | Fix | | --- | --- | --- | | `POST_ACCOUNT_MISMATCH` | Another account's `pst_` id | Use its X id | | `NOT_A_COMMENT` | The `cmt_` id is your own post | [Delete the post](/docs/post-lifecycle#delete-a-post) | | `UNSUPPORTED_PLATFORM` | Not on X, such as hiding a reply | Leave it out for X | | `ENGAGEMENT_PERMISSION`, `REPOST_PERMISSION`, `UNREPOST_PERMISSION` | X refused access | Reconnect and approve every permission | | `REPOSTS_UNAUTHORIZED`, `COMMENTS_PERMISSION` | X refused a list or a delete | Reconnect. For a delete, check the reply is yours | | `DUPLICATE_CONTENT` | A duplicate comment | Change the text | | `INSUFFICIENT_WALLET` | `402`. The wallet cannot cover it | [Top up](/docs/pricing#top-up) | ### Analytics Errors [#analytics-errors] | Code | Cause | Fix | | --- | --- | --- | | `POST_NOT_FOUND` | Deleted on X, or hidden from the account | Check the post on X | | `TIMELINE_UNSUPPORTED` | X has no daily timeline | Use Get Post Analytics | | `INSUFFICIENT_WALLET` | `402`. The day's read is not covered | [Top up](/docs/pricing#top-up) | # YouTube (/docs/youtube) Upload videos and Shorts, manage comments, like videos and read metrics. ## Quick Reference [#quick-reference] | Property | Value | | ------------------ | -------------------------------------- | | Account types | The signed-in Google account's channel | | Connection method | Google OAuth | | Post types | `video` | | Max media per post | 1 | | Text limit | 5,000 characters, title 100 | | Threads | No | | Quotes | No | | Remote delete | Yes | | Comments | Yes | | Likes | Yes | | Reposts | No | | Bookmarks | No | | Direct messages | No | | Post analytics | Yes | | Account analytics | No | Every post is exactly 1 video. Its `text` becomes the description. The title comes from the text unless you set `youtube.title`. ## Connect [#connect] Sign in with the Google account that owns the channel. Without a channel, it fails. Connect in **Dashboard → Connections**, or with a [connect session](/docs/connection). ### Permissions [#permissions] | Scope | Used for | | --- | --- | | `youtube.upload` | Uploading videos | | `youtube.force-ssl` | Comments, likes, deletes, uploads list and stats | | `yt-analytics.readonly` | Analytics, including shares | Google lets the owner skip permissions. Missing ones fail with a `*_PERMISSION` code until you reconnect and grant them. ### Staying Connected [#staying-connected] Access renews itself, so `canAutoRenew` is `true`. It ends if the owner removes access in Google. You then get `TOKEN_INVALID`. [Reconnect](/docs/account-status#reconnect-an-account) with the same Google account. The id stays the same. ## Publish [#publish] **TypeScript** ```typescript 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": "Build a REST API from scratch", "mediaKind": "video", "media": [ { "url": "https://cdn.onepostly.com/media/rest-api-tutorial.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_YOUTUBE_ACCOUNT_ID", "youtube": { "title": "Build a REST API from Scratch", "description": "A step by step walkthrough.\n\n00:00 Intro\n02:15 Routes", "privacyStatus": "public", "tags": [ "api", "tutorial" ], "categoryId": "27" } } ] }, }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) response = await posts_api.create_post( create_post_body={ "text": "Build a REST API from scratch", "mediaKind": "video", "media": [ { "url": "https://cdn.onepostly.com/media/rest-api-tutorial.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_YOUTUBE_ACCOUNT_ID", "youtube": { "title": "Build a REST API from Scratch", "description": "A step by step walkthrough.\n\n00:00 Intro\n02:15 Routes", "privacyStatus": "public", "tags": [ "api", "tutorial" ], "categoryId": "27" } } ] }, ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X POST "https://api.onepostly.com/v1/posts" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Build a REST API from scratch", "mediaKind": "video", "media": [ { "url": "https://cdn.onepostly.com/media/rest-api-tutorial.mp4" } ], "accounts": [ { "accountId": "acc_YOUR_YOUTUBE_ACCOUNT_ID", "youtube": { "title": "Build a REST API from Scratch", "description": "A step by step walkthrough.\n\n00:00 Intro\n02:15 Routes", "privacyStatus": "public", "tags": [ "api", "tutorial" ], "categoryId": "27" } } ] }' ``` **Response** ```json { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_YOUTUBE_ACCOUNT_ID", "platform": "youtube", "source": "onepostly", "status": "publishing", "text": "Build a REST API from scratch", "mediaKind": "video", "media": [ { "url": "https://cdn.onepostly.com/media/rest-api-tutorial.mp4" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": { "youtube": { "title": "Build a REST API from Scratch", "description": "A step by step walkthrough.\n\n00:00 Intro\n02:15 Routes", "privacyStatus": "public", "tags": [ "api", "tutorial" ], "categoryId": "27" } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } ] } ``` Once published, `platformPostId` is the video id and `url` its watch link. ### Post Types [#post-types] | `mediaKind` | Publishes | Media | | --- | --- | --- | | `video` | A video or a Short | Exactly 1 video, up to 256 MB | Any other `mediaKind` returns `400 VALIDATION_ERROR`. #### Shorts [#shorts] A Short is a normal upload, with no flag. YouTube decides by its shape. It must be vertical or square and up to 3 minutes long. ### Options [#options] Options go under `youtube`. Another platform's options there return `400`. | Field | Type | Description | | -------------------------------- | ------------------------------------- | ----------------------------------------------------------------- | | `accountId` (required) | `string` | The YouTube account id. | | `text` | `string` | This account's text, up to 5,000 characters. | | `youtube.title` | `string` | The title, 1 to 100 characters. Default `From the text`. | | `youtube.description` | `string` | The description, up to 5,000 characters. Default `The post text`. | | `youtube.privacyStatus` | `"public" \| "unlisted" \| "private"` | Who can watch, from publish on. Default `"public"`. | | `youtube.tags` | `string[]` | Up to 30 tags of 100 characters, 500 in total. | | `youtube.categoryId` | `string` | A YouTube category id. See below. Default `"22"`. | | `youtube.madeForKids` | `boolean` | Marks it for kids, which turns off comments. Default `false`. | | `youtube.containsSyntheticMedia` | `boolean` | Discloses realistic AI or altered content. | | `youtube.firstComment` | `string` | A channel comment after upload, up to 10,000 characters. | | `categoryId` | Category | | --- | --- | | `10` | Music | | `20` | Gaming | | `22` | People and Blogs | | `27` | Education | | `28` | Science and Technology | An unknown category fails the post with `VALIDATION_ERROR`. #### Title and Description [#title-and-description] Without `title`, the title is the text on one line, cut at 100 with `...`. Empty text gives the title "Untitled video". Without `description`, it is the text. Both are plain text, so Markdown and HTML show as typed. #### First Comment [#first-comment] If YouTube refuses `firstComment`, the video still publishes. A `madeForKids` video has comments off, so its first comment never posts. ### Media Requirements [#media-requirements] These are YouTube's limits, on top of the [Media URL Requirements](/docs/media-uploads#media-url-requirements). | Property | Requirement | | --- | --- | | Max size | 256 MB | | Recommended | MP4, H.264 and AAC | | Also accepted | MOV, AVI, WMV, FLV, 3GP, WebM | | Regular video | 16:9, 1080p or higher | | Short | 9:16 or 1:1, up to 3 minutes | | Duration | Up to 15 minutes without phone verification | A URL must send a `Content-Length` header. Uploaded files always do. Large videos keep processing after `published`. Do not upload again. ### Scheduling, Editing and Deleting [#scheduling-editing-and-deleting] [Scheduling and editing](/docs/scheduling) work as usual. The video uploads at the scheduled time. A published video returns `NOT_EDITABLE`. Delete it and upload it again. [Deleting](/docs/post-lifecycle#delete-a-post) removes the video. One already gone counts as deleted. A delete during upload returns `POST_PUBLISHING`. Outside videos return `NOT_DELETABLE`. ## Engagement [#engagement] See [Comments](/docs/comments) and [Likes and Reposts](/docs/engagement) for the requests. | Action | Supported | Notes | | --- | --- | --- | | List comments | Yes | Top-level, 50 per page, with some replies | | Comment or reply | Yes | As the channel, up to 10,000 characters | | Delete a comment | Yes | Ones the channel owns or moderates | | Like or unlike a video | Yes | Any video, as the channel | | Hide or like a comment | No | `UNSUPPORTED_PLATFORM` | | Repost, quote, bookmark | No | `UNSUPPORTED_PLATFORM` | Comments need the video's `pst_` id. Outside videos get one after a [sync](/docs/publishing#posts-made-outside-onepostly). Likes also take any YouTube video id. Another account's `pst_` id fails. **TypeScript** ```typescript import { Configuration, EngagementApi } from "@onepostly/sdk"; const engagementApi = new EngagementApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await engagementApi.likePost({ id: "acc_YOUR_YOUTUBE_ACCOUNT_ID", postId: "dQw4w9WgXcQ", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.engagement_api import EngagementApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: engagement_api = EngagementApi(api_client) response = await engagement_api.like_post( "acc_YOUR_YOUTUBE_ACCOUNT_ID", "dQw4w9WgXcQ", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X PUT "https://api.onepostly.com/v1/accounts/acc_YOUR_YOUTUBE_ACCOUNT_ID/likes/dQw4w9WgXcQ" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_YOUTUBE_ACCOUNT_ID", "platform": "youtube", "liked": true } ``` Commenting on a video with comments off returns `COMMENTS_PERMISSION`. ## Inbox [#inbox] YouTube has no inbox through Onepostly. ## Analytics [#analytics] ### Metrics [#metrics] | Field | YouTube metric | Notes | | --- | --- | --- | | `impressions` | Views | Same as `views` | | `reach` | None | Always `null` | | `views` | Views | | | `likes` | Likes | | | `comments` | Comments | | | `shares` | Shares | Needs `yt-analytics.readonly` | | `saves` | None | Always `null` | | `engagement` | Likes + comments + shares | | ### Read Post Analytics [#read-post-analytics] **TypeScript** ```typescript import { Configuration, AnalyticsApi } from "@onepostly/sdk"; const analyticsApi = new AnalyticsApi( new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }) ); const response = await analyticsApi.getPostAnalytics({ id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", }); console.log(response); ``` **Python** ```python import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.analytics_api import AnalyticsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: analytics_api = AnalyticsApi(api_client) response = await analytics_api.get_post_analytics( "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", ) print(response) asyncio.run(main()) ``` **cURL** ```bash curl -X GET "https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/analytics" \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` **Response** ```json { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "youtube", "status": "ready", "metrics": { "impressions": 456, "reach": null, "likes": 123, "comments": 12, "shares": 4, "saves": null, "views": 456, "engagement": 139 }, "fetchedAt": "2027-03-15T10:00:00.000Z", "error": null } ``` Freshness is the [standard](/docs/analytics#freshness). Shares arrive a few days after the rest. A new video reads `pending`. A private one can stay `pending` until you reconnect. A removed video reads `unavailable` with `VIDEO_NOT_FOUND`, for good. At capacity, it reads `failed` with `QUOTA_EXCEEDED` for a while. [List Account Media](/docs/api-reference/accounts/list-account-media) lists uploads, 20 per page. Its `metrics` and `durationSec` are `null`. It includes videos uploaded outside. ## Limitations [#limitations] Not available for YouTube through Onepostly. - Text and image posts - Threads and quotes - Custom thumbnails - Playlists, end screens and captions - Community posts, Premieres and live streams - Editing a published video - Deleting outside videos - Hiding or liking comments - Direct messages - Channel stats ## Errors [#errors] Breaking a rule on this page returns `400 VALIDATION_ERROR` and creates nothing. YouTube can also refuse the metadata at upload, failing the post the same way. Every code is in [Errors](/docs/error-handling), with its cause and fix. ### Publish Errors [#publish-errors] | Code | Cause | Fix | | --- | --- | --- | | `INVALID_MEDIA` | Empty, or over 256 MB | Send 1 video up to 256 MB | | `MEDIA_UNFETCHABLE` | No download, or no `Content-Length` | Upload the file instead | | `MEDIA_UPLOAD_FAILED` | YouTube rejected the file | Re-encode as MP4 | | `PUBLISH_FAILED` | YouTube did not confirm the upload | Check YouTube Studio first | | `UPLOAD_LIMIT_EXCEEDED` | YouTube's daily upload limit | Post again the next day | | `QUOTA_EXCEEDED` | YouTube is at capacity | Try again in a few hours | | `PERMISSION_DENIED` | A suspended channel or missing permission | Check the channel, then reconnect | | `NOT_EDITABLE` | An edit after publish | Delete and upload again | | `POST_PUBLISHING` | A delete during upload | Delete once `published` | ### Engagement Errors [#engagement-errors] | Code | Cause | Fix | | --- | --- | --- | | `POST_ACCOUNT_MISMATCH` | Another account's `pst_` id | Use the YouTube video id | | `COMMENTS_PERMISSION` | Comments off, or not the channel's comment | Turn comments on, or skip it | | `ENGAGEMENT_PERMISSION` | The channel cannot rate videos | Reconnect with every permission | ### Analytics Errors [#analytics-errors] | Code | Cause | Fix | | --- | --- | --- | | `ANALYTICS_PENDING` | No metrics yet | Read again later | | `VIDEO_NOT_FOUND` | The video is gone | Stop reading it | | `QUOTA_EXCEEDED` | YouTube is at capacity | Read again in a few hours | | `LIST_FAILED` | Uploads did not load | Try again later | # OpenAPI (/docs/openapi) The API is described by one OpenAPI 3.1 document. The [SDKs](/docs/sdks) and the [API Reference](/docs/api-reference) are generated from it, so they always match what the API accepts and returns. ## Download the Spec [#download-the-spec] ```bash curl -o onepostly-openapi.json https://api.onepostly.com/openapi.json ``` It is also at `https://onepostly.com/openapi.json`. Neither needs an API key. | Part | Contains | | --- | --- | | `paths` | Every API-key route, with its `operationId` and tag | | `components.schemas` | Request and response objects, plus `Error` and `ErrorCode` | | `components.parameters` | Shared ones, such as `cursor`, `limit` and `Idempotency-Key` | | `components.securitySchemes` | `Authorization: Bearer`. See [Authentication](/docs/authentication) | | `servers` | `https://api.onepostly.com` | | `webhooks` | Every event sent to your endpoint. See [below](#webhooks-in-the-spec) | Every route in it works with an API key, since dashboard-only routes are left out. New fields, routes and events can appear at any time. See the [Changelog](/docs/changelog). ## Generate a Client [#generate-a-client] The SDKs cover TypeScript and Python. For another language, use any OpenAPI 3.1 code generator. This example builds a Go client. ```bash npx @openapitools/openapi-generator-cli generate \ -i https://api.onepostly.com/openapi.json \ -g go \ -o ./onepostly-go ``` | Tip | Why | | --- | --- | | Generate from a saved copy | Your client changes only when you update it | | Keep unknown fields | Objects can gain fields at any time | | Keep open enums open | See [Open Enums](#open-enums) | | Send `Idempotency-Key` on `POST` | A retry never runs twice. See [Idempotency](/docs/idempotency) | ## Webhooks in the Spec [#webhooks-in-the-spec] The `webhooks` section has one entry per event type, such as `post.published`. Each entry has the delivery headers and the body schema. | Part | Contains | | --- | --- | | Headers | The `Onepostly-*` delivery headers and `User-Agent` | | Body | A schema per event, such as `PostPublishedEvent` | | Responses | Any `2xx` acknowledges it. See [Delivery](/docs/webhooks#delivery-and-retries) | Generate your handler's types from these schemas, then [verify the signature](/docs/webhooks#verify-signatures). Each event also has its own [API Reference page](/docs/api-reference/webhook-events/post-scheduled). ## Open Enums [#open-enums] A response field with listed values can gain new ones at any time, so handle a value you do not know. In the spec, it is `anyOf` the known values and any other string. ```json { "anyOf": [ { "type": "string", "enum": ["scheduled", "publishing", "published", "failed", "cancelled", "deleted"] }, { "type": "string" } ] } ``` Error `code` values are open too. Request fields are closed, and an unlisted value returns `400 VALIDATION_ERROR`. See [Data Formats](/docs/ids#open-enums) for every open field. ## Docs for AI Tools [#docs-for-ai-tools] Point an AI assistant at these to write code against the current API. | URL | Contains | | --- | --- | | [`/llms.txt`](https://onepostly.com/llms.txt) | Every page's title and description, with spec and docs links | | [`/llms-full.txt`](https://onepostly.com/llms-full.txt) | Every docs page as Markdown, in one file | | `/docs/.md` | One page as Markdown, such as [`/docs/quickstart.md`](https://onepostly.com/docs/quickstart.md) | Add `.md` to any docs URL for its Markdown, and the introduction is at `/docs.md`. Each page also has a **Copy Markdown** button under its title. To let an assistant act on your workspace, connect the [MCP Server](/docs/mcp). # Resources (/docs/resources) Tools for building on the Onepostly API, from typed SDKs to the spec they are generated from and docs formats for AI tools. - [SDKs](/docs/sdks): Official clients for Node.js and Python, generated from the OpenAPI spec. - [OpenAPI](/docs/openapi): The machine-readable API contract, with every route and webhook event. - [MCP Server](/docs/mcp): Manage posts from Claude, Cursor and other AI assistants. ## SDKs [#sdks] | Language | Package | Install | |---|---|---| | TypeScript and JavaScript | [`@onepostly/sdk`](https://www.npmjs.com/package/@onepostly/sdk) | `npm install @onepostly/sdk` | | Python | [`onepostly`](https://pypi.org/project/onepostly/) | `pip install onepostly` | Both SDKs are generated from the OpenAPI spec, so a new API field reaches them with the next release. Every request example in these docs has a TypeScript, a Python and a cURL tab. See [SDKs](/docs/sdks) for configuration, errors and paging. ## OpenAPI [#openapi] The spec lives at [`https://api.onepostly.com/openapi.json`](https://api.onepostly.com/openapi.json). It is OpenAPI 3.1 and covers every public route, the error responses and every webhook event. Use it to generate a client in another language, to type your webhook handler, or to import the API into an API testing tool. See [OpenAPI](/docs/openapi). ## LLMs.txt [#llmstxt] These docs are also published in formats that AI tools and coding agents read well. | URL | Contains | |---|---| | [`/llms.txt`](https://onepostly.com/llms.txt) | An index of every docs page with its description, plus links to the OpenAPI spec and the full docs | | [`/llms-full.txt`](https://onepostly.com/llms-full.txt) | Every docs page as Markdown in one file | | `/docs/.md` | One page as Markdown, such as [`/docs/quickstart.md`](https://onepostly.com/docs/quickstart.md) | Details are in [Docs for AI Tools](/docs/openapi#docs-for-ai-tools). # SDKs (/docs/sdks) The TypeScript and Python SDKs are generated from the [OpenAPI spec](/docs/openapi), so they cover every route in the [API Reference](/docs/api-reference) with typed requests and responses. Prefer plain HTTP? Every example has a cURL tab. See [Authentication](/docs/authentication). | Language | Package | Runs on | | --- | --- | --- | | TypeScript | [`@onepostly/sdk`](https://www.npmjs.com/package/@onepostly/sdk) | Node.js 18+, browsers and edge, no dependencies | | Python | [`onepostly`](https://pypi.org/project/onepostly/) | Python 3.10+, every method `async` | Each API Reference group is one class, such as `PostsApi` or `InboxApi`. Method names follow the operation ids, so [Create Post](/docs/api-reference/posts/create-post) is `createPost` or `create_post`. ## Node.js [#nodejs] ```bash npm install @onepostly/sdk ``` Create a `Configuration` with your API key and pass it to each API class you use. `accessToken` sends the key as `Authorization: Bearer`. ```ts title="publish.ts" import { Configuration, PostsApi } from "@onepostly/sdk"; const config = new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY }); const posts = new PostsApi(config); const created = await posts.createPost({ createPostBody: { text: "Hello from Onepostly", accounts: [{ accountId: "acc_YOUR_X_ACCOUNT_ID" }], }, }); console.log(created.groupId, created.data[0]?.status); ``` | Detail | How it works | | --- | --- | | Parameters | One object. The JSON body goes under its schema name, such as `createPostBody` | | Return value | The parsed body. `…Raw` methods, such as `createPostRaw`, add the `Response` | | Per-request options | The second argument changes the `fetch` call, such as headers or signal | | Base URL | `https://api.onepostly.com`. Change it with `basePath` | ## Python [#python] ```bash pip install onepostly ``` Create a `Configuration` with your API key, open an `ApiClient` with it, and pass that to each API class. `access_token` sends the key as `Authorization: Bearer`. ```python title="publish.py" import asyncio import os from onepostly import ApiClient, Configuration from onepostly.api.posts_api import PostsApi async def main() -> None: configuration = Configuration(access_token=os.environ["ONEPOSTLY_API_KEY"]) async with ApiClient(configuration) as api_client: posts_api = PostsApi(api_client) created = await posts_api.create_post( create_post_body={ "text": "Hello from Onepostly", "accounts": [{"accountId": "acc_YOUR_X_ACCOUNT_ID"}], }, ) print(created.group_id, created.data[0].status) asyncio.run(main()) ``` | Detail | How it works | | --- | --- | | Parameters | Keyword arguments. The body takes a model or a `dict` with API field names | | Return value | A typed model with snake_case attributes, such as `group_id` | | Status and headers | Call the `…_with_http_info` variant of the method | | Per-request options | `_headers` adds headers, and `_request_timeout` sets a timeout | | Base URL | `https://api.onepostly.com`. Change it with `host` | ## Errors [#errors] Every non-`2xx` response raises an error with the HTTP status and the [error body](/docs/error-handling#error-envelope). Branch on its `code`, and log its `requestId` for support. **TypeScript** A non-`2xx` response throws a `ResponseError`, with the `Response` in `response`. A network failure throws a `FetchError`, with the cause in `cause`. ```ts import { ResponseError } from "@onepostly/sdk"; try { await posts.createPost({ createPostBody: body }); } catch (error) { if (error instanceof ResponseError) { const { code, error: message, requestId } = await error.response.json(); console.error(error.response.status, code, message, requestId); } else { throw error; } } ``` **Python** A non-`2xx` response raises an `ApiException` with `status`, `reason`, `headers` and the raw JSON `body`. Common statuses raise a subclass. | Status | Raises | | --- | --- | | `400` | `BadRequestException` | | `401` | `UnauthorizedException` | | `403` | `ForbiddenException` | | `404` | `NotFoundException` | | `409` | `ConflictException` | | `422` | `UnprocessableEntityException` | | `5xx` | `ServiceException` | | Others, such as `402` and `429` | `ApiException` | ```python import json from onepostly import ApiException try: await posts_api.create_post(create_post_body=body) except ApiException as error: payload = json.loads(error.body or "{}") print(error.status, payload.get("code"), payload.get("error"), payload.get("requestId")) ``` Fields with listed values, such as `status`, can gain new ones. A new value does not break parsing, but your code must handle it. See [Open Enums](/docs/openapi#open-enums). ## Retries [#retries] The SDKs never retry on their own. Retry a `429`, a `5xx` or a network failure yourself, and wait for `Retry-After` as shown in [Handle 429 Responses](/docs/rate-limits#handle-429-responses). To retry a `POST` safely, send an `Idempotency-Key` and reuse it for every attempt. A repeat then returns the first response. See [Idempotent Requests](/docs/idempotency). **TypeScript** ```ts import { randomUUID } from "node:crypto"; const idempotencyKey = randomUUID(); await posts.createPost({ idempotencyKey, createPostBody: body }); ``` **Python** ```python import uuid idempotency_key = str(uuid.uuid4()) await posts_api.create_post( idempotency_key=idempotency_key, create_post_body=body, ) ``` ## Pagination [#pagination] Lists return `data`, `nextCursor` and `hasMore`. There is no paging helper, so pass `nextCursor` as `cursor` until `hasMore` is `false`. See [Pagination](/docs/pagination#pagination). **TypeScript** ```ts let cursor: string | undefined; do { const page = await posts.listPosts({ limit: 100, cursor }); for (const post of page.data) console.log(post.id, post.status); cursor = page.hasMore ? (page.nextCursor ?? undefined) : undefined; } while (cursor); ``` **Python** ```python cursor = None while True: page = await posts_api.list_posts(limit=100, cursor=cursor) for post in page.data: print(post.id, post.status) if not page.has_more: break cursor = page.next_cursor ``` ## Webhooks [#webhooks] The SDKs do not verify webhook signatures. Use the Node.js and Python functions in [Verify Signatures](/docs/webhooks#verify-signatures), and type your handler from the spec's [`webhooks` section](/docs/openapi#webhooks-in-the-spec). # Connect a Bluesky Account (/docs/api-reference/accounts/create-account) Connects a Bluesky account with its identifier and an App Password. Other platforms connect through Create Connect Session. `POST https://api.onepostly.com/v1/accounts` ```json { "paths": { "/v1/accounts": { "post": { "operationId": "createAccount", "tags": [ "Accounts" ], "summary": "Connect a Bluesky account", "description": "Connects a Bluesky account with its identifier and an App Password. Other platforms connect through Create Connect Session.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateAccountBody" } } } }, "responses": { "201": { "description": "Connected account", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Account" }, "example": { "id": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "bluesky", "displayName": "Your Brand", "handle": "yourbrand.bsky.social", "avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "status": "active", "canAutoRenew": true, "tokenExpiresAt": "2027-03-01T12:00:00.000Z", "profile": "Business", "metadata": { "userId": "user_8412" }, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z" } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or Bluesky could not sign in or the account could not be saved (CONNECT_FAILED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The new account needs a payment method (USAGE_BILLING_REQUIRED), or billing for it could not be set up (USAGE_BILLING_FAILED). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "409": { "$ref": "#/components/responses/ConflictReplayable" }, "422": { "description": "Bluesky refused the identifier or App Password (AUTH_FAILED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.createAccount({\n createAccountBody: {\n \"platform\": \"bluesky\",\n \"identifier\": \"yourbrand.bsky.social\",\n \"appPassword\": \"abcd-efgh-ijkl-mnop\",\n \"profile\": \"Business\",\n \"metadata\": {\n \"userId\": \"user_8412\"\n }\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.create_account(\n create_account_body={\n \"platform\": \"bluesky\",\n \"identifier\": \"yourbrand.bsky.social\",\n \"appPassword\": \"abcd-efgh-ijkl-mnop\",\n \"profile\": \"Business\",\n \"metadata\": {\n \"userId\": \"user_8412\"\n }\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/accounts\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"platform\": \"bluesky\",\n \"identifier\": \"yourbrand.bsky.social\",\n \"appPassword\": \"abcd-efgh-ijkl-mnop\",\n \"profile\": \"Business\",\n \"metadata\": {\n \"userId\": \"user_8412\"\n }\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Account": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "displayName": { "type": "string", "examples": [ "Onepostly" ] }, "handle": { "type": "string", "description": "The account's handle on the platform, without a leading @. LinkedIn has no handles, so a LinkedIn account has its name here.", "examples": [ "onepostly" ] }, "avatarUrl": { "type": [ "string", "null" ], "format": "uri", "examples": [ "https://cdn.onepostly.com/avatars/onepostly.jpg" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "active", "expired", "revoked", "error" ] }, { "type": "string" } ], "description": "active works normally. expired, revoked and error need a reconnect before the account can publish again. expired also covers an authorization that ran out and cannot renew by itself. A disconnected account is no longer returned. The account.disconnected webhook sends it as a DisconnectedAccount. New values can be added, so handle a value you do not know.", "examples": [ "active" ] }, "canAutoRenew": { "type": "boolean", "description": "Whether the authorization renews without the account owner signing in again.", "examples": [ true ] }, "tokenExpiresAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the current authorization expires, or null when it does not.", "examples": [ "2026-12-25T10:00:00.000Z" ] }, "profile": { "type": [ "string", "null" ], "description": "The name of the profile the account is filed under. null when the account is in no profile.", "examples": [ "Business" ] }, "metadata": { "$ref": "#/components/schemas/AccountMetadata", "description": "The metadata sent with the connect that added the account. An empty object when none was sent." }, "xSubscriptionType": { "type": [ "string", "null" ], "description": "X only, such as Premium. The account's X subscription, which sets its post length limit. Null when X does not report it, and left out for other platforms." }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "updatedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "platform", "displayName", "handle", "avatarUrl", "status", "canAutoRenew", "tokenExpiresAt", "profile", "metadata", "createdAt", "updatedAt" ] }, "AccountMetadata": { "type": "object", "additionalProperties": { "type": "string", "maxLength": 500 }, "description": "Your own key-value pairs for the account, such as the id of the user in your app who connected it. Up to 20 keys. Keys are 1 to 40 characters and values up to 500. Do not store secrets here.", "examples": [ { "userId": "user_8412" } ] }, "CreateAccountBody": { "type": "object", "properties": { "identifier": { "type": "string", "minLength": 1, "maxLength": 253, "description": "Bluesky handle, email or DID, such as alice.bsky.social.", "examples": [ "alice.bsky.social" ] }, "appPassword": { "type": "string", "minLength": 1, "maxLength": 200, "description": "A Bluesky App Password, in the form xxxx-xxxx-xxxx-xxxx. Create it in Bluesky under Settings, App Passwords.", "examples": [ "abcd-efgh-ijkl-mnop" ] }, "platform": { "type": "string", "enum": [ "bluesky" ], "description": "bluesky. Every other platform connects through a connect session, because the account owner signs in on the platform." }, "profile": { "type": "string", "minLength": 1, "maxLength": 60, "description": "Profile to file the account under. It is created if it does not exist. Defaults to the workspace's Default profile.", "examples": [ "Business" ] }, "metadata": { "$ref": "#/components/schemas/AccountMetadata", "description": "Your own key-value pairs for the account, such as the id of your user. The account returns them as metadata. An account that is already connected keeps its metadata." } }, "required": [ "identifier", "appPassword", "platform" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ConflictReplayable": { "description": "The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Disconnect Account (/docs/api-reference/accounts/delete-account) Disconnects the account. On YouTube, Onepostly's access is also withdrawn on the platform. Its published posts stay on the platform, and its posts in Onepostly keep their history. `DELETE https://api.onepostly.com/v1/accounts/{id}` ```json { "paths": { "/v1/accounts/{id}": { "delete": { "operationId": "deleteAccount", "tags": [ "Accounts" ], "summary": "Disconnect account", "description": "Disconnects the account. On YouTube, Onepostly's access is also withdrawn on the platform. Its published posts stay on the platform, and its posts in Onepostly keep their history.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" } ], "responses": { "204": { "description": "Disconnected", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.deleteAccount({\n id: \"acc_YOUR_LINKEDIN_ACCOUNT_ID\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.delete_account(\n \"acc_YOUR_LINKEDIN_ACCOUNT_ID\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/accounts/acc_YOUR_LINKEDIN_ACCOUNT_ID\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Account Stats (/docs/api-reference/accounts/get-account-stats) Returns live audience counts, such as followers and likes, for TikTok, Instagram, Facebook and Bluesky accounts. A count the platform does not report is null. `GET https://api.onepostly.com/v1/accounts/{id}/stats` ```json { "paths": { "/v1/accounts/{id}/stats": { "get": { "operationId": "getAccountStats", "tags": [ "Accounts" ], "summary": "Get account stats", "description": "Returns live audience counts, such as followers and likes, for TikTok, Instagram, Facebook and Bluesky accounts. A count the platform does not report is null.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" } ], "responses": { "200": { "description": "Account stats", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountStats" }, "example": { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "followerCount": 12480, "followingCount": 318, "likesCount": null, "videoCount": 642, "fetchedAt": "2027-03-15T10:00:00.000Z" } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the platform reports no account stats (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.getAccountStats({\n id: \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.get_account_stats(\n \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_INSTAGRAM_ACCOUNT_ID/stats\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "AccountStats": { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "followerCount": { "type": [ "integer", "null" ], "description": "Followers. Null when the platform does not report it.", "examples": [ 1234 ] }, "followingCount": { "type": [ "integer", "null" ], "description": "Accounts this account follows. Null when the platform does not report it.", "examples": [ 56 ] }, "likesCount": { "type": [ "integer", "null" ], "description": "TikTok: likes across the account's videos. Facebook: people who like the Page. Null on other platforms.", "examples": [ 7890 ] }, "videoCount": { "type": [ "integer", "null" ], "description": "Published posts. Videos on TikTok, media on Instagram and posts on Bluesky. Null on other platforms.", "examples": [ 12 ] }, "fetchedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "accountId", "platform", "followerCount", "followingCount", "likesCount", "videoCount", "fetchedAt" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Conflict": { "description": "The account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Account (/docs/api-reference/accounts/get-account) `GET https://api.onepostly.com/v1/accounts/{id}` ```json { "paths": { "/v1/accounts/{id}": { "get": { "operationId": "getAccount", "tags": [ "Accounts" ], "summary": "Get account", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" } ], "responses": { "200": { "description": "Account", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Account" }, "example": { "id": "acc_YOUR_LINKEDIN_ACCOUNT_ID", "platform": "linkedin", "displayName": "Your Brand", "handle": "Your Brand", "avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "status": "active", "canAutoRenew": false, "tokenExpiresAt": "2027-04-30T10:00:00.000Z", "profile": "Default", "metadata": {}, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.getAccount({\n id: \"acc_YOUR_LINKEDIN_ACCOUNT_ID\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.get_account(\n \"acc_YOUR_LINKEDIN_ACCOUNT_ID\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_LINKEDIN_ACCOUNT_ID\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Account": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "displayName": { "type": "string", "examples": [ "Onepostly" ] }, "handle": { "type": "string", "description": "The account's handle on the platform, without a leading @. LinkedIn has no handles, so a LinkedIn account has its name here.", "examples": [ "onepostly" ] }, "avatarUrl": { "type": [ "string", "null" ], "format": "uri", "examples": [ "https://cdn.onepostly.com/avatars/onepostly.jpg" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "active", "expired", "revoked", "error" ] }, { "type": "string" } ], "description": "active works normally. expired, revoked and error need a reconnect before the account can publish again. expired also covers an authorization that ran out and cannot renew by itself. A disconnected account is no longer returned. The account.disconnected webhook sends it as a DisconnectedAccount. New values can be added, so handle a value you do not know.", "examples": [ "active" ] }, "canAutoRenew": { "type": "boolean", "description": "Whether the authorization renews without the account owner signing in again.", "examples": [ true ] }, "tokenExpiresAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the current authorization expires, or null when it does not.", "examples": [ "2026-12-25T10:00:00.000Z" ] }, "profile": { "type": [ "string", "null" ], "description": "The name of the profile the account is filed under. null when the account is in no profile.", "examples": [ "Business" ] }, "metadata": { "$ref": "#/components/schemas/AccountMetadata", "description": "The metadata sent with the connect that added the account. An empty object when none was sent." }, "xSubscriptionType": { "type": [ "string", "null" ], "description": "X only, such as Premium. The account's X subscription, which sets its post length limit. Null when X does not report it, and left out for other platforms." }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "updatedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "platform", "displayName", "handle", "avatarUrl", "status", "canAutoRenew", "tokenExpiresAt", "profile", "metadata", "createdAt", "updatedAt" ] }, "AccountMetadata": { "type": "object", "additionalProperties": { "type": "string", "maxLength": 500 }, "description": "Your own key-value pairs for the account, such as the id of the user in your app who connected it. Up to 20 keys. Keys are 1 to 40 characters and values up to 500. Do not store secrets here.", "examples": [ { "userId": "user_8412" } ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Account Media (/docs/api-reference/accounts/list-account-media) Lists the account's posts on the platform, newest first, for X, Instagram, Facebook, Threads, TikTok, YouTube and Bluesky. The first page also includes the account's recent posts published through Onepostly. A count or length the platform does not report is null. Instagram also lists active stories with kind stories. `GET https://api.onepostly.com/v1/accounts/{id}/media` ```json { "paths": { "/v1/accounts/{id}/media": { "get": { "operationId": "listAccountMedia", "tags": [ "Accounts" ], "summary": "List account media", "description": "Lists the account's posts on the platform, newest first, for X, Instagram, Facebook, Threads, TikTok, YouTube and Bluesky. The first page also includes the account's recent posts published through Onepostly. A count or length the platform does not report is null. Instagram also lists active stories with kind stories.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "$ref": "#/components/parameters/Limit20Max20" }, { "$ref": "#/components/parameters/Cursor" }, { "schema": { "type": "string", "enum": [ "media", "stories" ], "description": "What to list. Defaults to media. stories is Instagram only.", "examples": [ "media" ] }, "required": false, "description": "What to list. Defaults to media. stories is Instagram only.", "name": "kind", "in": "query" } ], "responses": { "200": { "description": "Media", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/AccountMediaItem" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "1900912345678901234", "title": "Watch the 90-second walkthrough. https://t.co/Xk4p9QmZ2v", "description": "Watch the 90-second walkthrough. https://t.co/Xk4p9QmZ2v", "coverUrl": "https://pbs.twimg.com/amplify_video_thumb/1900912345678901234/img/Qm3nX8kP2rT5vW7y.jpg", "url": "https://x.com/yourbrand/status/1900912345678901234", "createdAt": "2027-03-14T16:30:12.000Z", "durationSec": 90, "metrics": { "likes": 86, "comments": 9, "shares": 14, "views": 5210 } }, { "id": "1900893456789012345", "title": "Ship day in 4 frames. https://t.co/Rb7nL2wQ8s", "description": "Ship day in 4 frames. https://t.co/Rb7nL2wQ8s", "coverUrl": "https://pbs.twimg.com/media/GkT3bQxWcAAz9Lp.jpg", "url": "https://x.com/yourbrand/status/1900893456789012345", "createdAt": "2027-03-14T11:05:47.000Z", "durationSec": null, "metrics": { "likes": 42, "comments": 3, "shares": 5, "views": 2318 } } ], "nextCursor": "7140dibdnow9c7btw4b0ld1ak2pzz6c1c2zuh0xb5c9yd", "hasMore": true } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the platform cannot list the account's posts, or kind is stories on an account that is not on Instagram (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.listAccountMedia({\n id: \"acc_YOUR_X_ACCOUNT_ID\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.list_account_media(\n \"acc_YOUR_X_ACCOUNT_ID\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_X_ACCOUNT_ID/media\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "AccountMediaItem": { "type": "object", "properties": { "id": { "type": "string", "description": "The platform's id for the item.", "examples": [ "7412345678901234567" ] }, "title": { "type": [ "string", "null" ], "description": "The item's title. Null when it has none.", "examples": [ "My trip" ] }, "description": { "type": [ "string", "null" ], "description": "The item's caption or description. Null when it has none.", "examples": [ "Weekend recap #travel" ] }, "coverUrl": { "type": [ "string", "null" ], "description": "Cover or thumbnail image URL. Null when the platform does not report one.", "examples": [ "https://cdn.onepostly.com/media/cover.jpg" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the item on the platform.", "examples": [ "https://www.tiktok.com/@you/video/7412345678901234567" ] }, "createdAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the item was published. Null when the platform does not report it.", "examples": [ "2026-08-20T10:00:00.000Z" ] }, "durationSec": { "type": [ "number", "null" ], "description": "Video length, in seconds. Null for images and text posts.", "examples": [ 42 ] }, "metrics": { "type": "object", "properties": { "likes": { "type": [ "integer", "null" ], "examples": [ 123 ] }, "comments": { "type": [ "integer", "null" ], "examples": [ 12 ] }, "shares": { "type": [ "integer", "null" ], "examples": [ 4 ] }, "views": { "type": [ "integer", "null" ], "examples": [ 4567 ] } }, "required": [ "likes", "comments", "shares", "views" ], "description": "Counts as the platform reports them now. A count the platform does not report is null." } }, "required": [ "id", "title", "description", "coverUrl", "url", "createdAt", "durationSec", "metrics" ] } }, "parameters": { "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit20Max20": { "schema": { "type": "integer", "minimum": 1, "maximum": 20, "default": 20, "description": "Items per page. Defaults to 20. Maximum 20.", "examples": [ 20 ] }, "required": false, "description": "Items per page. Defaults to 20. Maximum 20.", "name": "limit", "in": "query" }, "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Conflict": { "description": "The account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Accounts (/docs/api-reference/accounts/list-accounts) Lists the workspace's connected accounts, newest first. `GET https://api.onepostly.com/v1/accounts` ```json { "paths": { "/v1/accounts": { "get": { "operationId": "listAccounts", "tags": [ "Accounts" ], "summary": "List accounts", "description": "Lists the workspace's connected accounts, newest first.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/Limit50Max100" }, { "$ref": "#/components/parameters/Cursor" }, { "schema": { "type": "string", "maxLength": 200, "description": "Searches display name, handle and platform. Matching ignores case." }, "required": false, "description": "Searches display name, handle and platform. Matching ignores case.", "name": "q", "in": "query" }, { "schema": { "type": "string", "maxLength": 60, "description": "Only accounts filed under the profile with this name. Letter case does not matter. Use none for accounts without a profile.", "examples": [ "Business" ] }, "required": false, "description": "Only accounts filed under the profile with this name. Letter case does not matter. Use none for accounts without a profile.", "name": "profile", "in": "query" }, { "schema": { "type": "string", "maxLength": 64, "description": "Only accounts on this platform.", "examples": [ "instagram" ] }, "required": false, "description": "Only accounts on this platform.", "name": "platform", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "Only accounts connected at or after this time." }, "required": false, "description": "Only accounts connected at or after this time.", "name": "since", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "Only accounts connected before this time." }, "required": false, "description": "Only accounts connected before this time.", "name": "until", "in": "query" }, { "schema": { "type": "string", "enum": [ "created_desc", "created_asc" ], "description": "Order by connection time. Defaults to created_desc.", "examples": [ "created_desc" ] }, "required": false, "description": "Order by connection time. Defaults to created_desc.", "name": "sort", "in": "query" }, { "$ref": "#/components/parameters/Include" } ], "responses": { "200": { "description": "Accounts", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Account" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." }, "total": { "type": "integer", "description": "Items matching the filters across every page. Present when include has total." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "acc_1699f4157fb643f49d2ac447491f3203", "platform": "bluesky", "displayName": "Your Brand", "handle": "yourbrand.bsky.social", "avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "status": "active", "canAutoRenew": true, "tokenExpiresAt": "2027-03-01T12:10:00.000Z", "profile": "Business", "metadata": { "userId": "user_8412" }, "createdAt": "2027-03-01T10:10:00.000Z", "updatedAt": "2027-03-01T10:10:00.000Z" }, { "id": "acc_1699f4157fb643f49d2ac447491f3202", "platform": "instagram", "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": {}, "createdAt": "2027-03-01T10:05:00.000Z", "updatedAt": "2027-03-01T10:05:00.000Z" }, { "id": "acc_1699f4157fb643f49d2ac447491f32a8", "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": "Business", "metadata": {}, "xSubscriptionType": "None", "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z" } ], "nextCursor": null, "hasMore": false } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.listAccounts();\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.list_accounts()\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Account": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "displayName": { "type": "string", "examples": [ "Onepostly" ] }, "handle": { "type": "string", "description": "The account's handle on the platform, without a leading @. LinkedIn has no handles, so a LinkedIn account has its name here.", "examples": [ "onepostly" ] }, "avatarUrl": { "type": [ "string", "null" ], "format": "uri", "examples": [ "https://cdn.onepostly.com/avatars/onepostly.jpg" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "active", "expired", "revoked", "error" ] }, { "type": "string" } ], "description": "active works normally. expired, revoked and error need a reconnect before the account can publish again. expired also covers an authorization that ran out and cannot renew by itself. A disconnected account is no longer returned. The account.disconnected webhook sends it as a DisconnectedAccount. New values can be added, so handle a value you do not know.", "examples": [ "active" ] }, "canAutoRenew": { "type": "boolean", "description": "Whether the authorization renews without the account owner signing in again.", "examples": [ true ] }, "tokenExpiresAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the current authorization expires, or null when it does not.", "examples": [ "2026-12-25T10:00:00.000Z" ] }, "profile": { "type": [ "string", "null" ], "description": "The name of the profile the account is filed under. null when the account is in no profile.", "examples": [ "Business" ] }, "metadata": { "$ref": "#/components/schemas/AccountMetadata", "description": "The metadata sent with the connect that added the account. An empty object when none was sent." }, "xSubscriptionType": { "type": [ "string", "null" ], "description": "X only, such as Premium. The account's X subscription, which sets its post length limit. Null when X does not report it, and left out for other platforms." }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "updatedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "platform", "displayName", "handle", "avatarUrl", "status", "canAutoRenew", "tokenExpiresAt", "profile", "metadata", "createdAt", "updatedAt" ] }, "AccountMetadata": { "type": "object", "additionalProperties": { "type": "string", "maxLength": 500 }, "description": "Your own key-value pairs for the account, such as the id of the user in your app who connected it. Up to 20 keys. Keys are 1 to 40 characters and values up to 500. Do not store secrets here.", "examples": [ { "userId": "user_8412" } ] } }, "parameters": { "Include": { "schema": { "type": "string", "description": "Comma-separated extras to add to the response: total." }, "required": false, "description": "Comma-separated extras to add to the response: total.", "name": "include", "in": "query" }, "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max100": { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50, "description": "Items per page. Defaults to 50. Maximum 100.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 100.", "name": "limit", "in": "query" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Reconnect Account (/docs/api-reference/accounts/reconnect-account) Renews an account's authorization. For OAuth platforms the response has type oauth and url, where the account owner signs in again with the same account. For Bluesky, send identifier and appPassword and the response has type account and the reconnected account. Reconnecting never adds a billed account. `POST https://api.onepostly.com/v1/accounts/{id}/reconnect` ```json { "paths": { "/v1/accounts/{id}/reconnect": { "post": { "operationId": "reconnectAccount", "tags": [ "Accounts" ], "summary": "Reconnect account", "description": "Renews an account's authorization. For OAuth platforms the response has type oauth and url, where the account owner signs in again with the same account. For Bluesky, send identifier and appPassword and the response has type account and the reconnected account. Reconnecting never adds a billed account.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReconnectAccountBody" } } } }, "responses": { "200": { "description": "Authorization URL, or the reconnected Bluesky account", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReconnectAccountResult" }, "example": { "type": "oauth", "url": "https://www.linkedin.com/oauth/v2/authorization?response_type=code&state=eyJhbGciOiJIUzI1NiJ9", "expiresAt": "2027-03-15T10:10:00.000Z" } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), redirectUrl is missing or not a valid HTTPS URL (REDIRECT_URL_REQUIRED, INVALID_REDIRECT_URL), a Bluesky account was sent without identifier and appPassword (BLUESKY_RECONNECT_APP_PASSWORD), the credentials belong to another Bluesky account (RECONNECT_MISMATCH), or Bluesky could not sign in (CONNECT_FAILED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "$ref": "#/components/responses/NotFoundReplayable" }, "409": { "$ref": "#/components/responses/ConflictReplayable" }, "422": { "description": "Bluesky refused the identifier or App Password (AUTH_FAILED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "description": "The platform failed or did not respond, or accounts on it cannot be connected right now (PLATFORM_UNAVAILABLE). Try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "503": { "$ref": "#/components/responses/Unavailable" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.reconnectAccount({\n id: \"acc_YOUR_LINKEDIN_ACCOUNT_ID\",\n reconnectAccountBody: {\n \"redirectUrl\": \"https://yourapp.com/oauth/onepostly\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.reconnect_account(\n \"acc_YOUR_LINKEDIN_ACCOUNT_ID\",\n reconnect_account_body={\n \"redirectUrl\": \"https://yourapp.com/oauth/onepostly\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/accounts/acc_YOUR_LINKEDIN_ACCOUNT_ID/reconnect\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"redirectUrl\": \"https://yourapp.com/oauth/onepostly\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "ReconnectAccountResult": { "oneOf": [ { "$ref": "#/components/schemas/ReconnectAuthorization" }, { "$ref": "#/components/schemas/ReconnectedAccount" } ], "discriminator": { "propertyName": "type", "mapping": { "oauth": "#/components/schemas/ReconnectAuthorization", "account": "#/components/schemas/ReconnectedAccount" } }, "description": "type tells the two answers apart. oauth has url and expiresAt. account has the reconnected account." }, "ReconnectedAccount": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "account" ], "description": "Always account." }, "account": { "$ref": "#/components/schemas/Account", "description": "The reconnected account." } }, "required": [ "type", "account" ], "description": "The answer for Bluesky. The account is reconnected with the new App Password." }, "Account": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "displayName": { "type": "string", "examples": [ "Onepostly" ] }, "handle": { "type": "string", "description": "The account's handle on the platform, without a leading @. LinkedIn has no handles, so a LinkedIn account has its name here.", "examples": [ "onepostly" ] }, "avatarUrl": { "type": [ "string", "null" ], "format": "uri", "examples": [ "https://cdn.onepostly.com/avatars/onepostly.jpg" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "active", "expired", "revoked", "error" ] }, { "type": "string" } ], "description": "active works normally. expired, revoked and error need a reconnect before the account can publish again. expired also covers an authorization that ran out and cannot renew by itself. A disconnected account is no longer returned. The account.disconnected webhook sends it as a DisconnectedAccount. New values can be added, so handle a value you do not know.", "examples": [ "active" ] }, "canAutoRenew": { "type": "boolean", "description": "Whether the authorization renews without the account owner signing in again.", "examples": [ true ] }, "tokenExpiresAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the current authorization expires, or null when it does not.", "examples": [ "2026-12-25T10:00:00.000Z" ] }, "profile": { "type": [ "string", "null" ], "description": "The name of the profile the account is filed under. null when the account is in no profile.", "examples": [ "Business" ] }, "metadata": { "$ref": "#/components/schemas/AccountMetadata", "description": "The metadata sent with the connect that added the account. An empty object when none was sent." }, "xSubscriptionType": { "type": [ "string", "null" ], "description": "X only, such as Premium. The account's X subscription, which sets its post length limit. Null when X does not report it, and left out for other platforms." }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "updatedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "platform", "displayName", "handle", "avatarUrl", "status", "canAutoRenew", "tokenExpiresAt", "profile", "metadata", "createdAt", "updatedAt" ] }, "AccountMetadata": { "type": "object", "additionalProperties": { "type": "string", "maxLength": 500 }, "description": "Your own key-value pairs for the account, such as the id of the user in your app who connected it. Up to 20 keys. Keys are 1 to 40 characters and values up to 500. Do not store secrets here.", "examples": [ { "userId": "user_8412" } ] }, "ReconnectAuthorization": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "oauth" ], "description": "Always oauth." }, "url": { "type": "string", "format": "uri", "description": "Where the account owner signs in again.", "examples": [ "https://x.com/i/oauth2/authorize?response_type=code&state=abc123" ] }, "expiresAt": { "type": "string", "format": "date-time", "description": "When url stops working, in ISO 8601. A sign-in that finishes later returns to redirectUrl with error=SESSION_EXPIRED. Reconnect again then.", "examples": [ "2026-08-25T10:10:00.000Z" ] } }, "required": [ "type", "url", "expiresAt" ], "description": "The answer for an OAuth platform. The account owner signs in again at url." }, "ReconnectAccountBody": { "type": "object", "properties": { "redirectUrl": { "type": "string", "format": "uri", "description": "Where the browser returns after the owner signs in again. Required with an API key. Ignored for Bluesky.", "examples": [ "https://example.com/onepostly/callback" ] }, "identifier": { "type": "string", "minLength": 1, "maxLength": 253, "description": "Bluesky only. The account's handle, email or DID.", "examples": [ "alice.bsky.social" ] }, "appPassword": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Bluesky only. A new App Password for the account.", "examples": [ "abcd-efgh-ijkl-mnop" ] } } } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "Unavailable": { "description": "New connections to this platform are paused for now (PLATFORM_MAINTENANCE). Try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ConflictReplayable": { "description": "The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFoundReplayable": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Update Account (/docs/api-reference/accounts/update-account) Changes the account's metadata. A string sets a key, null removes it, and keys you leave out keep their values. `PATCH https://api.onepostly.com/v1/accounts/{id}` ```json { "paths": { "/v1/accounts/{id}": { "patch": { "operationId": "updateAccount", "tags": [ "Accounts" ], "summary": "Update account", "description": "Changes the account's metadata. A string sets a key, null removes it, and keys you leave out keep their values.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateAccountBody" } } } }, "responses": { "200": { "description": "Updated account", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Account" }, "example": { "id": "acc_1699f4157fb643f49d2ac447491f32a8", "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": "Business", "metadata": { "userId": "user_8412", "team": "marketing" }, "xSubscriptionType": "None", "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } } } }, "400": { "description": "The request is invalid, or the account would have more than 20 metadata keys (VALIDATION_ERROR)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.updateAccount({\n id: \"acc_1699f4157fb643f49d2ac447491f32a8\",\n updateAccountBody: {\n \"metadata\": {\n \"team\": \"marketing\"\n }\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.update_account(\n \"acc_1699f4157fb643f49d2ac447491f32a8\",\n update_account_body={\n \"metadata\": {\n \"team\": \"marketing\"\n }\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PATCH \"https://api.onepostly.com/v1/accounts/acc_1699f4157fb643f49d2ac447491f32a8\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"metadata\": {\n \"team\": \"marketing\"\n }\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Account": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "displayName": { "type": "string", "examples": [ "Onepostly" ] }, "handle": { "type": "string", "description": "The account's handle on the platform, without a leading @. LinkedIn has no handles, so a LinkedIn account has its name here.", "examples": [ "onepostly" ] }, "avatarUrl": { "type": [ "string", "null" ], "format": "uri", "examples": [ "https://cdn.onepostly.com/avatars/onepostly.jpg" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "active", "expired", "revoked", "error" ] }, { "type": "string" } ], "description": "active works normally. expired, revoked and error need a reconnect before the account can publish again. expired also covers an authorization that ran out and cannot renew by itself. A disconnected account is no longer returned. The account.disconnected webhook sends it as a DisconnectedAccount. New values can be added, so handle a value you do not know.", "examples": [ "active" ] }, "canAutoRenew": { "type": "boolean", "description": "Whether the authorization renews without the account owner signing in again.", "examples": [ true ] }, "tokenExpiresAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the current authorization expires, or null when it does not.", "examples": [ "2026-12-25T10:00:00.000Z" ] }, "profile": { "type": [ "string", "null" ], "description": "The name of the profile the account is filed under. null when the account is in no profile.", "examples": [ "Business" ] }, "metadata": { "$ref": "#/components/schemas/AccountMetadata", "description": "The metadata sent with the connect that added the account. An empty object when none was sent." }, "xSubscriptionType": { "type": [ "string", "null" ], "description": "X only, such as Premium. The account's X subscription, which sets its post length limit. Null when X does not report it, and left out for other platforms." }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "updatedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "platform", "displayName", "handle", "avatarUrl", "status", "canAutoRenew", "tokenExpiresAt", "profile", "metadata", "createdAt", "updatedAt" ] }, "AccountMetadata": { "type": "object", "additionalProperties": { "type": "string", "maxLength": 500 }, "description": "Your own key-value pairs for the account, such as the id of the user in your app who connected it. Up to 20 keys. Keys are 1 to 40 characters and values up to 500. Do not store secrets here.", "examples": [ { "userId": "user_8412" } ] }, "UpdateAccountBody": { "type": "object", "properties": { "metadata": { "oneOf": [ { "$ref": "#/components/schemas/AccountMetadataPatch" }, { "type": "null" } ], "description": "The metadata keys to set or remove. null removes every key." } }, "required": [ "metadata" ] }, "AccountMetadataPatch": { "type": "object", "additionalProperties": { "type": [ "string", "null" ], "maxLength": 500 }, "description": "The keys to change. A string sets the key and null removes it. Keys you leave out keep their values. The result can have up to 20 keys.", "examples": [ { "userId": "user_9001", "team": null } ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Account Analytics (/docs/api-reference/analytics/get-account-analytics) Returns account-level insights, read live from the platform. Available for Instagram professional accounts and Facebook Pages. `GET https://api.onepostly.com/v1/accounts/{id}/analytics` ```json { "paths": { "/v1/accounts/{id}/analytics": { "get": { "operationId": "getAccountAnalytics", "tags": [ "Analytics" ], "summary": "Get account analytics", "description": "Returns account-level insights, read live from the platform. Available for Instagram professional accounts and Facebook Pages.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Comma-separated metric names. Instagram defaults to views, reach, accounts_engaged and total_interactions. Facebook defaults to page_media_view, page_total_media_view_unique, page_post_engagements, page_follows and page_daily_follows_unique.", "examples": [ "views,reach,accounts_engaged" ] }, "required": false, "description": "Comma-separated metric names. Instagram defaults to views, reach, accounts_engaged and total_interactions. Facebook defaults to page_media_view, page_total_media_view_unique, page_post_engagements, page_follows and page_daily_follows_unique.", "name": "metrics", "in": "query" }, { "schema": { "type": "string", "enum": [ "day", "week", "days_28", "lifetime" ], "description": "Aggregation period. Defaults to day.", "examples": [ "day" ] }, "required": false, "description": "Aggregation period. Defaults to day.", "name": "period", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "Start of the range." }, "required": false, "description": "Start of the range.", "name": "since", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "End of the range." }, "required": false, "description": "End of the range.", "name": "until", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Instagram: breakdown for demographic metrics, such as age, city, country or gender." }, "required": false, "description": "Instagram: breakdown for demographic metrics, such as age, city, country or gender.", "name": "breakdown", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 32, "description": "Instagram: timeframe for demographic metrics, such as this_month or this_week." }, "required": false, "description": "Instagram: timeframe for demographic metrics, such as this_month or this_week.", "name": "timeframe", "in": "query" }, { "schema": { "type": "string", "enum": [ "total_value", "time_series" ], "description": "Instagram: total_value for one total over the period, time_series for daily values. When omitted, each metric is read the way Instagram reports it." }, "required": false, "description": "Instagram: total_value for one total over the period, time_series for daily values. When omitted, each metric is read the way Instagram reports it.", "name": "metricType", "in": "query" } ], "responses": { "200": { "description": "Account analytics", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountAnalytics" }, "example": { "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "metrics": [ { "name": "reach", "period": "day", "values": [ { "value": 3120, "endTime": null } ] }, { "name": "views", "period": "day", "values": [ { "value": 8450, "endTime": null } ] } ], "demographics": {} } } } }, "400": { "description": "The request is invalid or the platform cannot read the account with these metrics, period or breakdown (VALIDATION_ERROR), or the account is not an Instagram or Facebook account (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "description": "The account lacks the permission this read needs (ANALYTICS_PERMISSION, PERMISSION_DENIED). Reconnect it and grant insights access", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AnalyticsApi } from \"@onepostly/sdk\";\n\nconst analyticsApi = new AnalyticsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await analyticsApi.getAccountAnalytics({\n id: \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n metrics: \"reach,views\",\n period: \"day\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.analytics_api import AnalyticsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n analytics_api = AnalyticsApi(api_client)\n response = await analytics_api.get_account_analytics(\n \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n metrics=\"reach,views\",\n period=\"day\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_INSTAGRAM_ACCOUNT_ID/analytics?metrics=reach%2Cviews&period=day\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "AccountAnalytics": { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "metrics": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string", "description": "The metric, as the platform names it.", "examples": [ "reach" ] }, "period": { "type": "string", "description": "What each value covers, such as day, week, days_28 or lifetime.", "examples": [ "day" ] }, "values": { "type": "array", "items": { "type": "object", "properties": { "value": { "type": [ "number", "null" ], "description": "The metric's value. Null when the platform does not report it." }, "endTime": { "type": [ "string", "null" ], "format": "date-time", "description": "End of the period the value covers. Null when the platform does not report it.", "examples": [ "2026-08-25T07:00:00.000Z" ] } }, "required": [ "value", "endTime" ] } } }, "required": [ "name", "period", "values" ] }, "description": "One entry per metric, with its values over the period." }, "demographics": { "type": "object", "additionalProperties": { "type": "object", "additionalProperties": { "type": "number" } }, "description": "Breakdowns by dimension, keyed by metric name.", "examples": [ { "follower_demographics": { "US": 120, "TR": 80 } } ] } }, "required": [ "accountId", "platform", "metrics", "demographics" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Conflict": { "description": "The account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Post Analytics Timeline (/docs/api-reference/analytics/get-post-analytics-timeline) Returns a post's metrics day by day, one point per UTC day. Covers the last 90 days by default, and at most 90 days. Not available for X posts. `GET https://api.onepostly.com/v1/posts/{id}/analytics/timeline` ```json { "paths": { "/v1/posts/{id}/analytics/timeline": { "get": { "operationId": "getPostAnalyticsTimeline", "tags": [ "Analytics" ], "summary": "Get post analytics timeline", "description": "Returns a post's metrics day by day, one point per UTC day. Covers the last 90 days by default, and at most 90 days. Not available for X posts.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/PostId" }, { "schema": { "type": "string", "format": "date-time", "description": "Start of the range. The first day covered is the UTC day it falls on. Defaults to 90 days before until." }, "required": false, "description": "Start of the range. The first day covered is the UTC day it falls on. Defaults to 90 days before until.", "name": "since", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "End of the range. The last day covered is the UTC day the range ends in. Defaults to now." }, "required": false, "description": "End of the range. The last day covered is the UTC day the range ends in. Defaults to now.", "name": "until", "in": "query" } ], "responses": { "200": { "description": "Daily metrics", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostAnalyticsTimeline" }, "example": { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "from": "2027-03-01", "to": "2027-03-28", "points": [ { "day": "2027-03-15", "metrics": { "impressions": 310, "reach": 262, "likes": 28, "comments": 3, "shares": 1, "saves": 0, "views": 310, "engagement": 32 }, "delta": { "impressions": null, "reach": null, "likes": null, "comments": null, "shares": null, "saves": null, "views": null, "engagement": null } }, { "day": "2027-03-16", "metrics": { "impressions": 1980, "reach": 1610, "likes": 141, "comments": 13, "shares": 5, "saves": 3, "views": 1980, "engagement": 162 }, "delta": { "impressions": 1670, "reach": 1348, "likes": 113, "comments": 10, "shares": 4, "saves": 3, "views": 1670, "engagement": 130 } }, { "day": "2027-03-17", "metrics": { "impressions": 2650, "reach": 2140, "likes": 182, "comments": 17, "shares": 6, "saves": 4, "views": 2650, "engagement": 209 }, "delta": { "impressions": 670, "reach": 530, "likes": 41, "comments": 4, "shares": 1, "saves": 1, "views": 670, "engagement": 47 } }, { "day": "2027-03-18", "metrics": { "impressions": 3040, "reach": 2450, "likes": 207, "comments": 19, "shares": 7, "saves": 5, "views": 3040, "engagement": 238 }, "delta": { "impressions": 390, "reach": 310, "likes": 25, "comments": 2, "shares": 1, "saves": 1, "views": 390, "engagement": 29 } }, { "day": "2027-03-19", "metrics": { "impressions": 3290, "reach": 2650, "likes": 223, "comments": 21, "shares": 8, "saves": 6, "views": 3290, "engagement": 258 }, "delta": { "impressions": 250, "reach": 200, "likes": 16, "comments": 2, "shares": 1, "saves": 1, "views": 250, "engagement": 20 } }, { "day": "2027-03-20", "metrics": { "impressions": 3450, "reach": 2780, "likes": 233, "comments": 22, "shares": 8, "saves": 6, "views": 3450, "engagement": 269 }, "delta": { "impressions": 160, "reach": 130, "likes": 10, "comments": 1, "shares": 0, "saves": 0, "views": 160, "engagement": 11 } }, { "day": "2027-03-21", "metrics": { "impressions": 3570, "reach": 2870, "likes": 240, "comments": 23, "shares": 9, "saves": 7, "views": 3570, "engagement": 279 }, "delta": { "impressions": 120, "reach": 90, "likes": 7, "comments": 1, "shares": 1, "saves": 1, "views": 120, "engagement": 10 } }, { "day": "2027-03-22", "metrics": { "impressions": 3660, "reach": 2940, "likes": 245, "comments": 23, "shares": 9, "saves": 7, "views": 3660, "engagement": 284 }, "delta": { "impressions": 90, "reach": 70, "likes": 5, "comments": 0, "shares": 0, "saves": 0, "views": 90, "engagement": 5 } }, { "day": "2027-03-23", "metrics": { "impressions": 3730, "reach": 2990, "likes": 249, "comments": 24, "shares": 9, "saves": 7, "views": 3730, "engagement": 289 }, "delta": { "impressions": 70, "reach": 50, "likes": 4, "comments": 1, "shares": 0, "saves": 0, "views": 70, "engagement": 5 } }, { "day": "2027-03-24", "metrics": { "impressions": 3780, "reach": 3030, "likes": 252, "comments": 24, "shares": 9, "saves": 8, "views": 3780, "engagement": 293 }, "delta": { "impressions": 50, "reach": 40, "likes": 3, "comments": 0, "shares": 0, "saves": 1, "views": 50, "engagement": 4 } }, { "day": "2027-03-25", "metrics": { "impressions": 3820, "reach": 3060, "likes": 254, "comments": 24, "shares": 10, "saves": 8, "views": 3820, "engagement": 296 }, "delta": { "impressions": 40, "reach": 30, "likes": 2, "comments": 0, "shares": 1, "saves": 0, "views": 40, "engagement": 3 } }, { "day": "2027-03-26", "metrics": { "impressions": 3850, "reach": 3080, "likes": 256, "comments": 25, "shares": 10, "saves": 8, "views": 3850, "engagement": 299 }, "delta": { "impressions": 30, "reach": 20, "likes": 2, "comments": 1, "shares": 0, "saves": 0, "views": 30, "engagement": 3 } }, { "day": "2027-03-27", "metrics": { "impressions": 3870, "reach": 3095, "likes": 257, "comments": 25, "shares": 10, "saves": 8, "views": 3870, "engagement": 300 }, "delta": { "impressions": 20, "reach": 15, "likes": 1, "comments": 0, "shares": 0, "saves": 0, "views": 20, "engagement": 1 } }, { "day": "2027-03-28", "metrics": { "impressions": 3890, "reach": 3105, "likes": 258, "comments": 25, "shares": 10, "saves": 8, "views": 3890, "engagement": 301 }, "delta": { "impressions": 20, "reach": 10, "likes": 1, "comments": 0, "shares": 0, "saves": 0, "views": 20, "engagement": 1 } } ] } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), since is not before until or the range covers more than 90 days (INVALID_RANGE), or the post is on X (TIMELINE_UNSUPPORTED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No post with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AnalyticsApi } from \"@onepostly/sdk\";\n\nconst analyticsApi = new AnalyticsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await analyticsApi.getPostAnalyticsTimeline({\n id: \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n since: \"2027-03-01T00:00:00Z\",\n until: \"2027-03-29T00:00:00Z\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.analytics_api import AnalyticsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n analytics_api = AnalyticsApi(api_client)\n response = await analytics_api.get_post_analytics_timeline(\n \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n since=\"2027-03-01T00:00:00Z\",\n until=\"2027-03-29T00:00:00Z\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/analytics/timeline?since=2027-03-01T00%3A00%3A00Z&until=2027-03-29T00%3A00%3A00Z\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "PostAnalyticsTimeline": { "type": "object", "properties": { "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "from": { "type": "string", "format": "date", "description": "First UTC day of the timeline.", "examples": [ "2026-08-01" ] }, "to": { "type": "string", "format": "date", "description": "Last UTC day of the timeline.", "examples": [ "2026-08-28" ] }, "points": { "type": "array", "items": { "type": "object", "properties": { "day": { "type": "string", "format": "date", "description": "The UTC day.", "examples": [ "2026-08-01" ] }, "metrics": { "$ref": "#/components/schemas/PostMetrics", "description": "Lifetime totals from the first reading of the day." }, "delta": { "$ref": "#/components/schemas/PostMetrics", "description": "Change since the previous point." } }, "required": [ "day", "metrics", "delta" ] }, "description": "One point per UTC day with a reading. A day without a reading has no point." } }, "required": [ "postId", "from", "to", "points" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." } }, "parameters": { "PostId": { "schema": { "type": "string", "minLength": 1, "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Post Analytics (/docs/api-reference/analytics/get-post-analytics) Returns a post's lifetime metrics. Metrics refresh about hourly for posts under 30 days old and about weekly after that. X metrics are read when you ask and charged to the wallet, at most once per post and UTC day. Later requests that day return the same reading at no charge. `GET https://api.onepostly.com/v1/posts/{id}/analytics` ```json { "paths": { "/v1/posts/{id}/analytics": { "get": { "operationId": "getPostAnalytics", "tags": [ "Analytics" ], "summary": "Get post analytics", "description": "Returns a post's lifetime metrics. Metrics refresh about hourly for posts under 30 days old and about weekly after that. X metrics are read when you ask and charged to the wallet, at most once per post and UTC day. Later requests that day return the same reading at no charge.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/PostId" } ], "responses": { "200": { "description": "Post analytics", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostAnalytics" }, "example": { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "status": "ready", "metrics": { "impressions": 1456, "reach": 987, "likes": 123, "comments": 12, "shares": 4, "saves": 2, "views": 1456, "engagement": 141 }, "fetchedAt": "2027-03-15T10:00:00.000Z", "error": null } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the day's read of an X post (INSUFFICIENT_WALLET). Top up and send the request again. The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No post with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AnalyticsApi } from \"@onepostly/sdk\";\n\nconst analyticsApi = new AnalyticsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await analyticsApi.getPostAnalytics({\n id: \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.analytics_api import AnalyticsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n analytics_api = AnalyticsApi(api_client)\n response = await analytics_api.get_post_analytics(\n \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/analytics\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "PostAnalytics": { "type": "object", "properties": { "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "status": { "anyOf": [ { "type": "string", "enum": [ "ready", "pending", "failed", "unsupported", "unavailable" ] }, { "type": "string" } ], "description": "ready has metrics. pending waits for the platform's first reading. failed means the last reading failed, and error says why. unavailable means the post can never be measured, because it is not published or the platform never reports metrics for it, such as a deleted post or a TikTok post that is not public. unsupported means the platform has no post metrics. unavailable and unsupported are final. New values can be added, so handle a value you do not know." }, "metrics": { "$ref": "#/components/schemas/PostMetrics" }, "fetchedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the platform was last read. Null before the first reading, and for X, which is read when you ask.", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string", "description": "Human-readable reason for display." } }, "required": [ "code", "message" ], "description": "Why the last reading failed. Null otherwise." } }, "required": [ "postId", "accountId", "platform", "status", "metrics", "fetchedAt", "error" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." } }, "parameters": { "PostId": { "schema": { "type": "string", "minLength": 1, "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Create Automation (/docs/api-reference/automations/create-automation) Creates a keyword rule for an Instagram or Facebook account. An account can have up to 20 rules. `POST https://api.onepostly.com/v1/automations` ```json { "paths": { "/v1/automations": { "post": { "operationId": "createAutomation", "tags": [ "Automations" ], "summary": "Create automation", "description": "Creates a keyword rule for an Instagram or Facebook account. An account can have up to 20 rules.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateAutomationBody" } } } }, "responses": { "201": { "description": "Created automation", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Automation" }, "example": { "id": "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "name": "Free guide giveaway", "kind": "comment_to_dm", "keywords": [ "guide", "free" ], "excludeKeywords": [ "guidelines" ], "message": "Thanks for your interest! Here is your guide.", "enabled": true } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), the account is not on Instagram or Facebook (UNSUPPORTED_PLATFORM), or the account already has 20 automations (LIMIT_REACHED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "description": "No account with this accountId is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The account's automations changed while this request ran (CONFLICT). Send the request again. The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AutomationsApi } from \"@onepostly/sdk\";\n\nconst automationsApi = new AutomationsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await automationsApi.createAutomation({\n createAutomationBody: {\n \"accountId\": \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n \"kind\": \"comment_to_dm\",\n \"name\": \"Free guide giveaway\",\n \"keywords\": [\n \"guide\",\n \"free\"\n ],\n \"excludeKeywords\": [\n \"guidelines\"\n ],\n \"message\": \"Thanks for your interest! Here is your guide.\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.automations_api import AutomationsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n automations_api = AutomationsApi(api_client)\n response = await automations_api.create_automation(\n create_automation_body={\n \"accountId\": \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n \"kind\": \"comment_to_dm\",\n \"name\": \"Free guide giveaway\",\n \"keywords\": [\n \"guide\",\n \"free\"\n ],\n \"excludeKeywords\": [\n \"guidelines\"\n ],\n \"message\": \"Thanks for your interest! Here is your guide.\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/automations\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"accountId\": \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n \"kind\": \"comment_to_dm\",\n \"name\": \"Free guide giveaway\",\n \"keywords\": [\n \"guide\",\n \"free\"\n ],\n \"excludeKeywords\": [\n \"guidelines\"\n ],\n \"message\": \"Thanks for your interest! Here is your guide.\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Automation": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "name": { "type": "string", "description": "Label for the rule.", "examples": [ "Free guide giveaway" ] }, "kind": { "anyOf": [ { "type": "string", "enum": [ "comment_to_dm", "story_reply", "welcome_dm" ] }, { "type": "string" } ], "description": "comment_to_dm answers a comment with a direct message. story_reply answers a reply to a story. welcome_dm answers a message. New values can be added, so handle a value you do not know." }, "keywords": { "type": "array", "items": { "type": "string" }, "description": "The rule runs when a comment or message contains any of these words. Matching ignores case.", "examples": [ [ "guide", "free" ] ] }, "excludeKeywords": { "type": "array", "items": { "type": "string" }, "description": "The rule is skipped when a comment or message contains any of these words.", "examples": [ [ "guidelines" ] ] }, "message": { "type": "string", "description": "The direct message the rule sends.", "examples": [ "Thanks for your interest! Here is your guide." ] }, "enabled": { "type": "boolean", "description": "false while the rule is paused." } }, "required": [ "id", "accountId", "name", "kind", "keywords", "excludeKeywords", "message", "enabled" ] }, "CreateAutomationBody": { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "An Instagram or Facebook account from List Accounts." }, "kind": { "type": "string", "enum": [ "comment_to_dm", "story_reply", "welcome_dm" ], "description": "comment_to_dm answers a comment with a direct message. story_reply answers a reply to a story. welcome_dm answers a message." }, "name": { "type": "string", "minLength": 1, "maxLength": 120, "description": "Label for the rule." }, "keywords": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 200 }, "minItems": 1, "maxItems": 20, "description": "The rule runs when a comment or message contains any of these words. Matching ignores case." }, "excludeKeywords": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 200 }, "maxItems": 20, "description": "The rule is skipped when a comment or message contains any of these words." }, "message": { "type": "string", "minLength": 1, "maxLength": 1000, "description": "The direct message the rule sends." }, "enabled": { "type": "boolean", "description": "Defaults to true." } }, "required": [ "accountId", "kind", "name", "keywords", "message" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Delete Automation (/docs/api-reference/automations/delete-automation) `DELETE https://api.onepostly.com/v1/automations/{id}` ```json { "paths": { "/v1/automations/{id}": { "delete": { "operationId": "deleteAutomation", "tags": [ "Automations" ], "summary": "Delete automation", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AutomationId" } ], "responses": { "204": { "description": "Deleted", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No automation with this id (NOT_FOUND), or its account is no longer connected (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The account's automations changed while this request ran (CONFLICT). Send the request again", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AutomationsApi } from \"@onepostly/sdk\";\n\nconst automationsApi = new AutomationsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await automationsApi.deleteAutomation({\n id: \"aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.automations_api import AutomationsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n automations_api = AutomationsApi(api_client)\n response = await automations_api.delete_automation(\n \"aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/automations/aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] } }, "parameters": { "AutomationId": { "schema": { "type": "string", "minLength": 1, "examples": [ "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Automation (/docs/api-reference/automations/get-automation) `GET https://api.onepostly.com/v1/automations/{id}` ```json { "paths": { "/v1/automations/{id}": { "get": { "operationId": "getAutomation", "tags": [ "Automations" ], "summary": "Get automation", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AutomationId" } ], "responses": { "200": { "description": "Automation", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Automation" }, "example": { "id": "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "name": "Free guide giveaway", "kind": "comment_to_dm", "keywords": [ "guide", "free" ], "excludeKeywords": [ "guidelines" ], "message": "Thanks for your interest! Here is your guide.", "enabled": true } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No automation with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AutomationsApi } from \"@onepostly/sdk\";\n\nconst automationsApi = new AutomationsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await automationsApi.getAutomation({\n id: \"aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.automations_api import AutomationsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n automations_api = AutomationsApi(api_client)\n response = await automations_api.get_automation(\n \"aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/automations/aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Automation": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "name": { "type": "string", "description": "Label for the rule.", "examples": [ "Free guide giveaway" ] }, "kind": { "anyOf": [ { "type": "string", "enum": [ "comment_to_dm", "story_reply", "welcome_dm" ] }, { "type": "string" } ], "description": "comment_to_dm answers a comment with a direct message. story_reply answers a reply to a story. welcome_dm answers a message. New values can be added, so handle a value you do not know." }, "keywords": { "type": "array", "items": { "type": "string" }, "description": "The rule runs when a comment or message contains any of these words. Matching ignores case.", "examples": [ [ "guide", "free" ] ] }, "excludeKeywords": { "type": "array", "items": { "type": "string" }, "description": "The rule is skipped when a comment or message contains any of these words.", "examples": [ [ "guidelines" ] ] }, "message": { "type": "string", "description": "The direct message the rule sends.", "examples": [ "Thanks for your interest! Here is your guide." ] }, "enabled": { "type": "boolean", "description": "false while the rule is paused." } }, "required": [ "id", "accountId", "name", "kind", "keywords", "excludeKeywords", "message", "enabled" ] } }, "parameters": { "AutomationId": { "schema": { "type": "string", "minLength": 1, "examples": [ "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Automations (/docs/api-reference/automations/list-automations) Lists the keyword rules of the workspace's Instagram and Facebook accounts. Accounts come oldest first, and each account's rules in the order they were created. `GET https://api.onepostly.com/v1/automations` ```json { "paths": { "/v1/automations": { "get": { "operationId": "listAutomations", "tags": [ "Automations" ], "summary": "List automations", "description": "Lists the keyword rules of the workspace's Instagram and Facebook accounts. Accounts come oldest first, and each account's rules in the order they were created.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/Limit50Max100" }, { "$ref": "#/components/parameters/Cursor" }, { "schema": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "Only the rules of this account." }, "required": false, "description": "Only the rules of this account.", "name": "accountId", "in": "query" } ], "responses": { "200": { "description": "Automations", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Automation" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "name": "Free guide giveaway", "kind": "comment_to_dm", "keywords": [ "guide", "free" ], "excludeKeywords": [ "guidelines" ], "message": "Thanks for your interest! Here is your guide.", "enabled": true }, { "id": "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a02", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "name": "Welcome message", "kind": "welcome_dm", "keywords": [ "hi", "hello" ], "excludeKeywords": [], "message": "Thanks for reaching out! We reply within a day.", "enabled": false } ], "nextCursor": null, "hasMore": false } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not on Instagram or Facebook (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No account with this accountId is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AutomationsApi } from \"@onepostly/sdk\";\n\nconst automationsApi = new AutomationsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await automationsApi.listAutomations({\n accountId: \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.automations_api import AutomationsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n automations_api = AutomationsApi(api_client)\n response = await automations_api.list_automations(\n account_id=\"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/automations?accountId=acc_YOUR_INSTAGRAM_ACCOUNT_ID\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Automation": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "name": { "type": "string", "description": "Label for the rule.", "examples": [ "Free guide giveaway" ] }, "kind": { "anyOf": [ { "type": "string", "enum": [ "comment_to_dm", "story_reply", "welcome_dm" ] }, { "type": "string" } ], "description": "comment_to_dm answers a comment with a direct message. story_reply answers a reply to a story. welcome_dm answers a message. New values can be added, so handle a value you do not know." }, "keywords": { "type": "array", "items": { "type": "string" }, "description": "The rule runs when a comment or message contains any of these words. Matching ignores case.", "examples": [ [ "guide", "free" ] ] }, "excludeKeywords": { "type": "array", "items": { "type": "string" }, "description": "The rule is skipped when a comment or message contains any of these words.", "examples": [ [ "guidelines" ] ] }, "message": { "type": "string", "description": "The direct message the rule sends.", "examples": [ "Thanks for your interest! Here is your guide." ] }, "enabled": { "type": "boolean", "description": "false while the rule is paused." } }, "required": [ "id", "accountId", "name", "kind", "keywords", "excludeKeywords", "message", "enabled" ] } }, "parameters": { "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max100": { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50, "description": "Items per page. Defaults to 50. Maximum 100.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 100.", "name": "limit", "in": "query" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Update Automation (/docs/api-reference/automations/update-automation) Changes a rule. Only the fields you send change. Send enabled false to pause it. `PATCH https://api.onepostly.com/v1/automations/{id}` ```json { "paths": { "/v1/automations/{id}": { "patch": { "operationId": "updateAutomation", "tags": [ "Automations" ], "summary": "Update automation", "description": "Changes a rule. Only the fields you send change. Send enabled false to pause it.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AutomationId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateAutomationBody" } } } }, "responses": { "200": { "description": "Updated automation", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Automation" }, "example": { "id": "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "name": "Free guide giveaway", "kind": "comment_to_dm", "keywords": [ "guide", "free" ], "excludeKeywords": [ "guidelines" ], "message": "Thanks for your interest! Here is your guide.", "enabled": false } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No automation with this id (NOT_FOUND), or its account is no longer connected (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The account's automations changed while this request ran (CONFLICT). Send the request again", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AutomationsApi } from \"@onepostly/sdk\";\n\nconst automationsApi = new AutomationsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await automationsApi.updateAutomation({\n id: \"aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33\",\n updateAutomationBody: {\n \"enabled\": false\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.automations_api import AutomationsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n automations_api = AutomationsApi(api_client)\n response = await automations_api.update_automation(\n \"aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33\",\n update_automation_body={\n \"enabled\": false\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PATCH \"https://api.onepostly.com/v1/automations/aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"enabled\": false\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Automation": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "name": { "type": "string", "description": "Label for the rule.", "examples": [ "Free guide giveaway" ] }, "kind": { "anyOf": [ { "type": "string", "enum": [ "comment_to_dm", "story_reply", "welcome_dm" ] }, { "type": "string" } ], "description": "comment_to_dm answers a comment with a direct message. story_reply answers a reply to a story. welcome_dm answers a message. New values can be added, so handle a value you do not know." }, "keywords": { "type": "array", "items": { "type": "string" }, "description": "The rule runs when a comment or message contains any of these words. Matching ignores case.", "examples": [ [ "guide", "free" ] ] }, "excludeKeywords": { "type": "array", "items": { "type": "string" }, "description": "The rule is skipped when a comment or message contains any of these words.", "examples": [ [ "guidelines" ] ] }, "message": { "type": "string", "description": "The direct message the rule sends.", "examples": [ "Thanks for your interest! Here is your guide." ] }, "enabled": { "type": "boolean", "description": "false while the rule is paused." } }, "required": [ "id", "accountId", "name", "kind", "keywords", "excludeKeywords", "message", "enabled" ] }, "UpdateAutomationBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 120, "description": "Label for the rule." }, "keywords": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 200 }, "minItems": 1, "maxItems": 20, "description": "Replaces the keywords. The rule runs when a comment or message contains any of them." }, "excludeKeywords": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 200 }, "maxItems": 20, "description": "Replaces the excluded keywords. Send an empty list to remove them." }, "message": { "type": "string", "minLength": 1, "maxLength": 1000, "description": "The direct message the rule sends." }, "enabled": { "type": "boolean", "description": "false pauses the rule, true resumes it." } } } }, "parameters": { "AutomationId": { "schema": { "type": "string", "minLength": 1, "examples": [ "aut_4b8e2f6a1c9d4e37a5b02c8f6d1e9a33" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Account Settings (/docs/api-reference/bluesky/get-account-settings) Returns the account's publishing defaults. Available for Bluesky accounts. `GET https://api.onepostly.com/v1/accounts/{id}/settings` ```json { "paths": { "/v1/accounts/{id}/settings": { "get": { "operationId": "getAccountSettings", "tags": [ "Accounts" ], "summary": "Get account settings", "description": "Returns the account's publishing defaults. Available for Bluesky accounts.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" } ], "responses": { "200": { "description": "Settings", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountSettings" }, "example": { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "defaultLangs": [ "en" ] } } } }, "400": { "description": "The account is not a Bluesky account (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.getAccountSettings({\n id: \"acc_YOUR_BLUESKY_ACCOUNT_ID\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.get_account_settings(\n \"acc_YOUR_BLUESKY_ACCOUNT_ID\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_BLUESKY_ACCOUNT_ID/settings\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "AccountSettings": { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "defaultLangs": { "type": [ "array", "null" ], "items": { "type": "string" }, "description": "Bluesky: languages applied to a post that names none. Null when unset.", "examples": [ [ "en" ] ] } }, "required": [ "accountId", "defaultLangs" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Update Account Settings (/docs/api-reference/bluesky/update-account-settings) Sets or clears the account's publishing defaults. Send null to clear a value. `PATCH https://api.onepostly.com/v1/accounts/{id}/settings` ```json { "paths": { "/v1/accounts/{id}/settings": { "patch": { "operationId": "updateAccountSettings", "tags": [ "Accounts" ], "summary": "Update account settings", "description": "Sets or clears the account's publishing defaults. Send null to clear a value.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateAccountSettingsBody" } } } }, "responses": { "200": { "description": "Updated settings", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountSettings" }, "example": { "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "defaultLangs": [ "en" ] } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not a Bluesky account (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.updateAccountSettings({\n id: \"acc_YOUR_BLUESKY_ACCOUNT_ID\",\n updateAccountSettingsBody: {\n \"defaultLangs\": [\n \"en\"\n ]\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.update_account_settings(\n \"acc_YOUR_BLUESKY_ACCOUNT_ID\",\n update_account_settings_body={\n \"defaultLangs\": [\n \"en\"\n ]\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PATCH \"https://api.onepostly.com/v1/accounts/acc_YOUR_BLUESKY_ACCOUNT_ID/settings\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"defaultLangs\": [\n \"en\"\n ]\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "AccountSettings": { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "defaultLangs": { "type": [ "array", "null" ], "items": { "type": "string" }, "description": "Bluesky: languages applied to a post that names none. Null when unset.", "examples": [ [ "en" ] ] } }, "required": [ "accountId", "defaultLangs" ] }, "UpdateAccountSettingsBody": { "type": "object", "properties": { "defaultLangs": { "type": [ "array", "null" ], "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Bluesky: language tags, such as en or pt, applied to a post that names none. Up to 3. null clears them.", "examples": [ [ "en" ] ] } }, "required": [ "defaultLangs" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Comment on a Post (/docs/api-reference/comments/create-comment) Posts a comment on the post as the account that published it. Supported on X, Instagram, Facebook, Threads, YouTube and Bluesky. `POST https://api.onepostly.com/v1/posts/{id}/comments` ```json { "paths": { "/v1/posts/{id}/comments": { "post": { "operationId": "createComment", "tags": [ "Comments" ], "summary": "Comment on a post", "description": "Posts a comment on the post as the account that published it. Supported on X, Instagram, Facebook, Threads, YouTube and Bluesky.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/PostId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentTextBody" } } } }, "responses": { "201": { "description": "Created comment", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Comment" }, "example": { "id": "cmt_jDn7AR68Du8FrawkvedZhy5qdVdXf8RMwWvtDCyDlOrDKhCBUKiix6E0T0FqW3UCGizpXZkVbUZ5b3uBVb8DDqwU0wRr4eoefhlGX0uQc6y2iCPDboTCpG", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "platformCommentId": "18063456789012345", "parentId": null, "text": "Thanks for watching!", "username": null, "likeCount": 0, "createdAt": "2027-03-15T10:00:00.000Z", "replies": [] } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), the text is over the platform's limit (TEXT_TOO_LONG), or the platform does not support this on the post (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the X action (INSUFFICIENT_WALLET). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "description": "No post with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID). The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefusedReplayable" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, CommentsApi } from \"@onepostly/sdk\";\n\nconst commentsApi = new CommentsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await commentsApi.createComment({\n id: \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n commentTextBody: {\n \"text\": \"Thanks for watching!\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.comments_api import CommentsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n comments_api = CommentsApi(api_client)\n response = await comments_api.create_comment(\n \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n comment_text_body={\n \"text\": \"Thanks for watching!\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/comments\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"text\": \"Thanks for watching!\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Comment": { "type": "object", "properties": { "id": { "type": "string", "description": "The comment's id. Use it to reply to, hide, like or delete the comment.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post the comment is on." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that published the post." }, "platform": { "$ref": "#/components/schemas/Platform" }, "platformCommentId": { "type": "string", "description": "The platform's own id for the comment.", "examples": [ "17895695668004550" ] }, "parentId": { "type": [ "string", "null" ], "description": "The comment this one replies to, or null for a comment on the post." }, "text": { "type": "string", "examples": [ "Love this!" ] }, "username": { "type": [ "string", "null" ], "description": "The author's username, without a leading @. Null when the platform does not share it.", "examples": [ "jane_doe" ] }, "likeCount": { "type": [ "integer", "null" ], "description": "Likes on the comment. Null when the platform does not report it.", "examples": [ 12 ] }, "createdAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the comment was posted. Null when the platform does not report it.", "examples": [ "2026-08-25T10:05:00.000Z" ] }, "replies": { "type": "array", "items": { "$ref": "#/components/schemas/Comment" }, "description": "Replies, on platforms that return them with the comment." } }, "required": [ "id", "postId", "accountId", "platform", "platformCommentId", "parentId", "text", "username", "likeCount", "createdAt", "replies" ] }, "CommentTextBody": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 25000, "description": "The comment text. The platform's own limit applies, such as 300 characters on Bluesky or 2,200 on Instagram. A longer text returns TEXT_TOO_LONG.", "examples": [ "Thanks for watching!" ] } }, "required": [ "text" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "PostId": { "schema": { "type": "string", "minLength": 1, "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefusedReplayable": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Delete Comment (/docs/api-reference/comments/delete-comment) Deletes a comment as the account that published the post. Supported on X, Instagram, Facebook, Threads, YouTube and Bluesky. `DELETE https://api.onepostly.com/v1/comments/{id}` ```json { "paths": { "/v1/comments/{id}": { "delete": { "operationId": "deleteComment", "tags": [ "Comments" ], "summary": "Delete comment", "description": "Deletes a comment as the account that published the post. Supported on X, Instagram, Facebook, Threads, YouTube and Bluesky.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/CommentId" } ], "responses": { "204": { "description": "Deleted", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } } }, "400": { "description": "The id names one of your published posts rather than a comment (NOT_A_COMMENT), or the platform does not support this on the post (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the X action (INSUFFICIENT_WALLET). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No comment with this id, or its post is gone (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, CommentsApi } from \"@onepostly/sdk\";\n\nconst commentsApi = new CommentsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await commentsApi.deleteComment({\n id: \"cmt_YOUR_COMMENT\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.comments_api import CommentsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n comments_api = CommentsApi(api_client)\n response = await comments_api.delete_comment(\n \"cmt_YOUR_COMMENT\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/comments/cmt_YOUR_COMMENT\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] } }, "parameters": { "CommentId": { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "required": true, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Hide Comment (/docs/api-reference/comments/hide-comment) Hides a comment on the account's post. The author still sees it. Supported on Instagram, Facebook and Threads. `PUT https://api.onepostly.com/v1/comments/{id}/hidden` ```json { "paths": { "/v1/comments/{id}/hidden": { "put": { "operationId": "hideComment", "tags": [ "Comments" ], "summary": "Hide comment", "description": "Hides a comment on the account's post. The author still sees it. Supported on Instagram, Facebook and Threads.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/CommentId" } ], "responses": { "200": { "description": "Hidden", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentVisibility" }, "example": { "id": "cmt_YOUR_COMMENT", "hidden": true } } } }, "400": { "description": "The platform does not support this on the post (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No comment with this id, or its post is gone (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, CommentsApi } from \"@onepostly/sdk\";\n\nconst commentsApi = new CommentsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await commentsApi.hideComment({\n id: \"cmt_YOUR_COMMENT\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.comments_api import CommentsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n comments_api = CommentsApi(api_client)\n response = await comments_api.hide_comment(\n \"cmt_YOUR_COMMENT\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PUT \"https://api.onepostly.com/v1/comments/cmt_YOUR_COMMENT/hidden\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "CommentVisibility": { "type": "object", "properties": { "id": { "type": "string", "description": "The comment's id." }, "hidden": { "type": "boolean", "description": "true while the comment is hidden." } }, "required": [ "id", "hidden" ] } }, "parameters": { "CommentId": { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "required": true, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Like Comment (/docs/api-reference/comments/like-comment) Likes a comment as the account that published the post. Supported on Facebook. `PUT https://api.onepostly.com/v1/comments/{id}/like` ```json { "paths": { "/v1/comments/{id}/like": { "put": { "operationId": "likeComment", "tags": [ "Comments" ], "summary": "Like comment", "description": "Likes a comment as the account that published the post. Supported on Facebook.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/CommentId" } ], "responses": { "200": { "description": "Liked", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentLike" }, "example": { "id": "cmt_YOUR_COMMENT", "liked": true } } } }, "400": { "description": "The platform does not support this on the post (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No comment with this id, or its post is gone (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, CommentsApi } from \"@onepostly/sdk\";\n\nconst commentsApi = new CommentsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await commentsApi.likeComment({\n id: \"cmt_YOUR_COMMENT\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.comments_api import CommentsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n comments_api = CommentsApi(api_client)\n response = await comments_api.like_comment(\n \"cmt_YOUR_COMMENT\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PUT \"https://api.onepostly.com/v1/comments/cmt_YOUR_COMMENT/like\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "CommentLike": { "type": "object", "properties": { "id": { "type": "string", "description": "The comment's id." }, "liked": { "type": "boolean", "description": "true while the account likes the comment." } }, "required": [ "id", "liked" ] } }, "parameters": { "CommentId": { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "required": true, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Comments (/docs/api-reference/comments/list-comments) Lists the comments on a post, read live from the platform. Supported on X, Instagram, Facebook, Threads, YouTube and Bluesky. `GET https://api.onepostly.com/v1/posts/{id}/comments` ```json { "paths": { "/v1/posts/{id}/comments": { "get": { "operationId": "listComments", "tags": [ "Comments" ], "summary": "List comments", "description": "Lists the comments on a post, read live from the platform. Supported on X, Instagram, Facebook, Threads, YouTube and Bluesky.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/PostId" }, { "$ref": "#/components/parameters/Limit50Max50" }, { "$ref": "#/components/parameters/Cursor" } ], "responses": { "200": { "description": "Comments", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Comment" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "cmt_amtpCkVartn0nqaE1Je0v2VkSEm03WARoWPFRyRgiFzkP3uEcxR4W9LztUdBGz2YWD5AFw9KMvsNTqsnW544OSHrpC1iYD3cgpan0HmOMKINUmnERALRze", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "platformCommentId": "17988123456789012", "parentId": null, "text": "Great results, congrats!", "username": "mark.builds", "likeCount": 0, "createdAt": "2027-03-15T09:42:19.000Z", "replies": [] }, { "id": "cmt_cDQEpthzkh9NCjzItFNd19ItnVdYlB4tB4t92XY6Edv1B72jDW9DvSpwIgqi6O75UgGzjUt3zONixH1SGrdIkBYuTm34IsLyxwSJLHBgdYz5DYn31g4zQ0", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "platformCommentId": "18050512345678901", "parentId": null, "text": "Love this! Where can I get one?", "username": "jane_doe", "likeCount": 3, "createdAt": "2027-03-15T09:20:11.000Z", "replies": [ { "id": "cmt_8c86vC3o0CyUONgnTCe2CNWfzeYcEfSNcRGHQeDTlVL6dsCpsa0OptpfZ9BoWxAPeFYf82BGoYyBMqDIOfv3NcCyj5R6TP7RcXGj8OcZEOBnRYy4q42spq", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "platformCommentId": "18050598765432109", "parentId": "cmt_cDQEpthzkh9NCjzItFNd19ItnVdYlB4tB4t92XY6Edv1B72jDW9DvSpwIgqi6O75UgGzjUt3zONixH1SGrdIkBYuTm34IsLyxwSJLHBgdYz5DYn31g4zQ0", "text": "The link is in our bio!", "username": "yourbrand", "likeCount": 1, "createdAt": "2027-03-15T09:24:37.000Z", "replies": [] } ] } ], "nextCursor": "QVFIUjRtc2N5ZAWZAkV3ZA0bHBpTlJXNWdVaU5GUEI3c1BtX0VnSzFnYWZAkdC1QWFZAiR0Q5ZAVNfNlBhTHVoa2RnMEtsSVlyTkhz", "hasMore": true } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the platform does not support this on the post (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover reading an X post's comments (INSUFFICIENT_WALLET). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No post with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, CommentsApi } from \"@onepostly/sdk\";\n\nconst commentsApi = new CommentsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await commentsApi.listComments({\n id: \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n limit: 25,\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.comments_api import CommentsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n comments_api = CommentsApi(api_client)\n response = await comments_api.list_comments(\n \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n limit=25,\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/comments?limit=25\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Comment": { "type": "object", "properties": { "id": { "type": "string", "description": "The comment's id. Use it to reply to, hide, like or delete the comment.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post the comment is on." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that published the post." }, "platform": { "$ref": "#/components/schemas/Platform" }, "platformCommentId": { "type": "string", "description": "The platform's own id for the comment.", "examples": [ "17895695668004550" ] }, "parentId": { "type": [ "string", "null" ], "description": "The comment this one replies to, or null for a comment on the post." }, "text": { "type": "string", "examples": [ "Love this!" ] }, "username": { "type": [ "string", "null" ], "description": "The author's username, without a leading @. Null when the platform does not share it.", "examples": [ "jane_doe" ] }, "likeCount": { "type": [ "integer", "null" ], "description": "Likes on the comment. Null when the platform does not report it.", "examples": [ 12 ] }, "createdAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the comment was posted. Null when the platform does not report it.", "examples": [ "2026-08-25T10:05:00.000Z" ] }, "replies": { "type": "array", "items": { "$ref": "#/components/schemas/Comment" }, "description": "Replies, on platforms that return them with the comment." } }, "required": [ "id", "postId", "accountId", "platform", "platformCommentId", "parentId", "text", "username", "likeCount", "createdAt", "replies" ] } }, "parameters": { "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max50": { "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 50, "description": "Items per page. Defaults to 50. Maximum 50.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 50.", "name": "limit", "in": "query" }, "PostId": { "schema": { "type": "string", "minLength": 1, "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Reply to a Comment (/docs/api-reference/comments/reply-to-comment) Replies to a comment as the account that published the post. `POST https://api.onepostly.com/v1/comments/{id}/replies` ```json { "paths": { "/v1/comments/{id}/replies": { "post": { "operationId": "replyToComment", "tags": [ "Comments" ], "summary": "Reply to a comment", "description": "Replies to a comment as the account that published the post.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/CommentId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentTextBody" } } } }, "responses": { "201": { "description": "Created reply", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Comment" }, "example": { "id": "cmt_ztfnHfaU0iNb9UBUuNnnxN8waYgVvu3Y12mVBDR6dweXoMSb4tn0DeDwvC0IeIW2SQEWLo9bNYoYFOPhESI4pxuKjN5txdk2pDjSaIaePIKjvOpsFJ26lA", "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_1699f4157fb643f49d2ac447491f32a8", "platform": "instagram", "platformCommentId": "18063456789012399", "parentId": "cmt_YOUR_COMMENT_ID", "text": "Glad you liked it.", "username": null, "likeCount": 0, "createdAt": "2027-03-15T10:00:00.000Z", "replies": [] } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), the text is over the platform's limit (TEXT_TOO_LONG), or the platform does not support this on the post (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the X action (INSUFFICIENT_WALLET). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "description": "No comment with this id, or its post is gone (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID). The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefusedReplayable" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, CommentsApi } from \"@onepostly/sdk\";\n\nconst commentsApi = new CommentsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await commentsApi.replyToComment({\n id: \"cmt_YOUR_COMMENT_ID\",\n commentTextBody: {\n \"text\": \"Glad you liked it.\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.comments_api import CommentsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n comments_api = CommentsApi(api_client)\n response = await comments_api.reply_to_comment(\n \"cmt_YOUR_COMMENT_ID\",\n comment_text_body={\n \"text\": \"Glad you liked it.\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/comments/cmt_YOUR_COMMENT_ID/replies\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"text\": \"Glad you liked it.\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Comment": { "type": "object", "properties": { "id": { "type": "string", "description": "The comment's id. Use it to reply to, hide, like or delete the comment.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post the comment is on." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that published the post." }, "platform": { "$ref": "#/components/schemas/Platform" }, "platformCommentId": { "type": "string", "description": "The platform's own id for the comment.", "examples": [ "17895695668004550" ] }, "parentId": { "type": [ "string", "null" ], "description": "The comment this one replies to, or null for a comment on the post." }, "text": { "type": "string", "examples": [ "Love this!" ] }, "username": { "type": [ "string", "null" ], "description": "The author's username, without a leading @. Null when the platform does not share it.", "examples": [ "jane_doe" ] }, "likeCount": { "type": [ "integer", "null" ], "description": "Likes on the comment. Null when the platform does not report it.", "examples": [ 12 ] }, "createdAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the comment was posted. Null when the platform does not report it.", "examples": [ "2026-08-25T10:05:00.000Z" ] }, "replies": { "type": "array", "items": { "$ref": "#/components/schemas/Comment" }, "description": "Replies, on platforms that return them with the comment." } }, "required": [ "id", "postId", "accountId", "platform", "platformCommentId", "parentId", "text", "username", "likeCount", "createdAt", "replies" ] }, "CommentTextBody": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 25000, "description": "The comment text. The platform's own limit applies, such as 300 characters on Bluesky or 2,200 on Instagram. A longer text returns TEXT_TOO_LONG.", "examples": [ "Thanks for watching!" ] } }, "required": [ "text" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "CommentId": { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "required": true, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefusedReplayable": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Send Private Reply (/docs/api-reference/comments/send-private-reply) Sends a direct message to the author of a comment. Supported on Instagram and Facebook, once per comment and within 7 days of it. `POST https://api.onepostly.com/v1/comments/{id}/private-reply` ```json { "paths": { "/v1/comments/{id}/private-reply": { "post": { "operationId": "sendPrivateReply", "tags": [ "Comments" ], "summary": "Send private reply", "description": "Sends a direct message to the author of a comment. Supported on Instagram and Facebook, once per comment and within 7 days of it.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/CommentId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PrivateReplyBody" } } } }, "responses": { "201": { "description": "Sent message", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PrivateReply" }, "example": { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM3NjE5NzM2Mzg3MTI4", "commentId": "cmt_YOUR_COMMENT_ID", "text": "Thanks! Check your DMs.", "createdAt": "2027-03-15T10:00:00.000Z" } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), the text is over the platform's limit (TEXT_TOO_LONG), or the platform does not support this on the post (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "description": "No comment with this id, or its post is gone (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID). The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefusedReplayable" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, CommentsApi } from \"@onepostly/sdk\";\n\nconst commentsApi = new CommentsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await commentsApi.sendPrivateReply({\n id: \"cmt_YOUR_COMMENT_ID\",\n privateReplyBody: {\n \"text\": \"Thanks! Check your DMs.\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.comments_api import CommentsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n comments_api = CommentsApi(api_client)\n response = await comments_api.send_private_reply(\n \"cmt_YOUR_COMMENT_ID\",\n private_reply_body={\n \"text\": \"Thanks! Check your DMs.\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/comments/cmt_YOUR_COMMENT_ID/private-reply\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"text\": \"Thanks! Check your DMs.\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "PrivateReply": { "type": "object", "properties": { "id": { "type": "string", "description": "The platform's id for the message." }, "commentId": { "type": "string", "description": "The comment the message answers." }, "text": { "type": "string", "description": "The message text as sent." }, "createdAt": { "type": "string", "format": "date-time", "description": "When the message was sent.", "examples": [ "2026-08-25T10:07:00.000Z" ] } }, "required": [ "id", "commentId", "text", "createdAt" ] }, "PrivateReplyBody": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 2000, "description": "The message text, up to 1,000 characters on Instagram and 2,000 on Facebook. A longer text returns TEXT_TOO_LONG.", "examples": [ "Thanks! Check your DMs." ] } }, "required": [ "text" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "CommentId": { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "required": true, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefusedReplayable": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Unhide Comment (/docs/api-reference/comments/unhide-comment) Shows a hidden comment again. Supported on Instagram, Facebook and Threads. `DELETE https://api.onepostly.com/v1/comments/{id}/hidden` ```json { "paths": { "/v1/comments/{id}/hidden": { "delete": { "operationId": "unhideComment", "tags": [ "Comments" ], "summary": "Unhide comment", "description": "Shows a hidden comment again. Supported on Instagram, Facebook and Threads.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/CommentId" } ], "responses": { "200": { "description": "Visible", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentVisibility" }, "example": { "id": "cmt_1favcqJ4EESecYNmroaaaU1lO77s9mVKL017fGpcyOCXzsOinAYE2V5yWPBhZ68L0CYTTX9fr03ZhAwJnw97HmmAVb2FHvTHo07uXsI1FmxybkJDsoXqqTqM7L9XPoZo1VVuWZtGwe", "hidden": false } } } }, "400": { "description": "The platform does not support this on the post (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No comment with this id, or its post is gone (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, CommentsApi } from \"@onepostly/sdk\";\n\nconst commentsApi = new CommentsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await commentsApi.unhideComment({\n id: \"cmt_1favcqJ4EESecYNmroaaaU1lO77s9mVKL017fGpcyOCXzsOinAYE2V5yWPBhZ68L0CYTTX9fr03ZhAwJnw97HmmAVb2FHvTHo07uXsI1FmxybkJDsoXqqTqM7L9XPoZo1VVuWZtGwe\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.comments_api import CommentsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n comments_api = CommentsApi(api_client)\n response = await comments_api.unhide_comment(\n \"cmt_1favcqJ4EESecYNmroaaaU1lO77s9mVKL017fGpcyOCXzsOinAYE2V5yWPBhZ68L0CYTTX9fr03ZhAwJnw97HmmAVb2FHvTHo07uXsI1FmxybkJDsoXqqTqM7L9XPoZo1VVuWZtGwe\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/comments/cmt_1favcqJ4EESecYNmroaaaU1lO77s9mVKL017fGpcyOCXzsOinAYE2V5yWPBhZ68L0CYTTX9fr03ZhAwJnw97HmmAVb2FHvTHo07uXsI1FmxybkJDsoXqqTqM7L9XPoZo1VVuWZtGwe/hidden\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "CommentVisibility": { "type": "object", "properties": { "id": { "type": "string", "description": "The comment's id." }, "hidden": { "type": "boolean", "description": "true while the comment is hidden." } }, "required": [ "id", "hidden" ] } }, "parameters": { "CommentId": { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "required": true, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Unlike Comment (/docs/api-reference/comments/unlike-comment) Removes the account's like from a comment. Supported on Facebook. `DELETE https://api.onepostly.com/v1/comments/{id}/like` ```json { "paths": { "/v1/comments/{id}/like": { "delete": { "operationId": "unlikeComment", "tags": [ "Comments" ], "summary": "Unlike comment", "description": "Removes the account's like from a comment. Supported on Facebook.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/CommentId" } ], "responses": { "200": { "description": "Unliked", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentLike" }, "example": { "id": "cmt_1favcqJ4EESecYNmroaaaU1lO77s9mVKL017fGpcyOCXzsOinAYE2V5yWPBhZ68L0CYTTX9fr03ZhAwJnw97HmmAVb2FHvTHo07uXsI1FmxybkJDsoXqqTqM7L9XPoZo1VVuWZtGwe", "liked": false } } } }, "400": { "description": "The platform does not support this on the post (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No comment with this id, or its post is gone (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, CommentsApi } from \"@onepostly/sdk\";\n\nconst commentsApi = new CommentsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await commentsApi.unlikeComment({\n id: \"cmt_1favcqJ4EESecYNmroaaaU1lO77s9mVKL017fGpcyOCXzsOinAYE2V5yWPBhZ68L0CYTTX9fr03ZhAwJnw97HmmAVb2FHvTHo07uXsI1FmxybkJDsoXqqTqM7L9XPoZo1VVuWZtGwe\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.comments_api import CommentsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n comments_api = CommentsApi(api_client)\n response = await comments_api.unlike_comment(\n \"cmt_1favcqJ4EESecYNmroaaaU1lO77s9mVKL017fGpcyOCXzsOinAYE2V5yWPBhZ68L0CYTTX9fr03ZhAwJnw97HmmAVb2FHvTHo07uXsI1FmxybkJDsoXqqTqM7L9XPoZo1VVuWZtGwe\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/comments/cmt_1favcqJ4EESecYNmroaaaU1lO77s9mVKL017fGpcyOCXzsOinAYE2V5yWPBhZ68L0CYTTX9fr03ZhAwJnw97HmmAVb2FHvTHo07uXsI1FmxybkJDsoXqqTqM7L9XPoZo1VVuWZtGwe/like\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "CommentLike": { "type": "object", "properties": { "id": { "type": "string", "description": "The comment's id." }, "liked": { "type": "boolean", "description": "true while the account likes the comment." } }, "required": [ "id", "liked" ] } }, "parameters": { "CommentId": { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "required": true, "description": "A comment id from List Comments or a comment event. It only works in the workspace that received it.", "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Create Connect Session (/docs/api-reference/connect/create-connect-session) Starts connecting an account. Send the account owner's browser to url, where they sign in on the platform. `POST https://api.onepostly.com/v1/connect-sessions` ```json { "paths": { "/v1/connect-sessions": { "post": { "operationId": "createConnectSession", "tags": [ "Connect" ], "summary": "Create connect session", "description": "Starts connecting an account. Send the account owner's browser to url, where they sign in on the platform.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateConnectSessionBody" } } } }, "responses": { "201": { "description": "Connect session", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConnectSession" }, "example": { "url": "https://x.com/i/oauth2/authorize?response_type=code&state=eyJhbGciOiJIUzI1NiJ9", "expiresAt": "2027-03-15T09:10:00.000Z" } } } }, "400": { "$ref": "#/components/responses/BadRequestReplayable" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "Connecting another account needs a payment method. The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "409": { "$ref": "#/components/responses/ConflictReplayable" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "description": "The platform failed or did not respond, or accounts on it cannot be connected right now (PLATFORM_UNAVAILABLE). Try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "503": { "$ref": "#/components/responses/Unavailable" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, ConnectApi } from \"@onepostly/sdk\";\n\nconst connectApi = new ConnectApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await connectApi.createConnectSession({\n createConnectSessionBody: {\n \"platform\": \"x\",\n \"redirectUrl\": \"https://yourapp.com/oauth/onepostly\",\n \"profile\": \"Business\",\n \"metadata\": {\n \"userId\": \"user_8412\"\n }\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.connect_api import ConnectApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n connect_api = ConnectApi(api_client)\n response = await connect_api.create_connect_session(\n create_connect_session_body={\n \"platform\": \"x\",\n \"redirectUrl\": \"https://yourapp.com/oauth/onepostly\",\n \"profile\": \"Business\",\n \"metadata\": {\n \"userId\": \"user_8412\"\n }\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/connect-sessions\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"platform\": \"x\",\n \"redirectUrl\": \"https://yourapp.com/oauth/onepostly\",\n \"profile\": \"Business\",\n \"metadata\": {\n \"userId\": \"user_8412\"\n }\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "ConnectSession": { "type": "object", "properties": { "url": { "type": "string", "format": "uri", "description": "Where the account owner signs in.", "examples": [ "https://x.com/i/oauth2/authorize?response_type=code&state=abc123" ] }, "expiresAt": { "type": "string", "format": "date-time", "description": "When url stops working, in ISO 8601. A sign-in that finishes later returns to redirectUrl with error=SESSION_EXPIRED. Create a new connect session then.", "examples": [ "2026-08-25T10:10:00.000Z" ] } }, "required": [ "url", "expiresAt" ] }, "CreateConnectSessionBody": { "type": "object", "properties": { "platform": { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest" ], "description": "Platform to connect. Bluesky connects with an App Password through Create Account instead.", "examples": [ "x" ] }, "redirectUrl": { "type": "string", "format": "uri", "description": "Where the browser returns when the connect finishes. Required with an API key. The connected account id arrives as the accountId query parameter.", "examples": [ "https://example.com/onepostly/callback" ] }, "profile": { "type": "string", "minLength": 1, "maxLength": 60, "description": "Profile to file the new account under. It is created if it does not exist. Defaults to the workspace's Default profile.", "examples": [ "Business" ] }, "metadata": { "$ref": "#/components/schemas/AccountMetadata", "description": "Your own key-value pairs for the new account, such as the id of your user. The account returns them as metadata, and so does the account.connected webhook. An account that is already connected keeps its metadata." }, "headless": { "type": "boolean", "description": "Facebook, and Instagram with facebook_login. True skips the hosted account picker: the browser returns to redirectUrl with connectSession, and you finish with List Candidates and Select Candidate. Requires redirectUrl." }, "loginMethod": { "type": "string", "enum": [ "instagram_login", "facebook_login" ], "description": "Instagram only. instagram_login (default) signs in to Instagram directly. facebook_login connects an Instagram account linked to a Facebook Page, which unlocks Page-linked features such as audio search." } }, "required": [ "platform" ] }, "AccountMetadata": { "type": "object", "additionalProperties": { "type": "string", "maxLength": 500 }, "description": "Your own key-value pairs for the account, such as the id of the user in your app who connected it. Up to 20 keys. Keys are 1 to 40 characters and values up to 500. Do not store secrets here.", "examples": [ { "userId": "user_8412" } ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "Unavailable": { "description": "New connections to this platform are paused for now (PLATFORM_MAINTENANCE). Try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ConflictReplayable": { "description": "The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequestReplayable": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Candidates (/docs/api-reference/connect/list-connect-candidates) Lists the Facebook Pages, or the Page-linked Instagram accounts, the account owner can connect in a headless connect session. `GET https://api.onepostly.com/v1/connect-sessions/{sessionId}/candidates` ```json { "paths": { "/v1/connect-sessions/{sessionId}/candidates": { "get": { "operationId": "listConnectCandidates", "tags": [ "Connect" ], "summary": "List candidates", "description": "Lists the Facebook Pages, or the Page-linked Instagram accounts, the account owner can connect in a headless connect session.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/SessionId" } ], "responses": { "200": { "description": "Candidates", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ConnectCandidate" } } }, "required": [ "data" ] }, "example": { "data": [ { "id": "123456789012345", "platform": "facebook", "name": "Your Brand", "username": "yourbrand", "pictureUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg", "category": "Brand", "pageName": null }, { "id": "123456789012346", "platform": "facebook", "name": "Your Brand Support", "username": "yourbrandsupport", "pictureUrl": "https://cdn.onepostly.com/avatars/yourbrandsupport.jpg", "category": "Product/service", "pageName": null } ] } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "The connect session was started by another workspace. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, ConnectApi } from \"@onepostly/sdk\";\n\nconst connectApi = new ConnectApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await connectApi.listConnectCandidates({\n sessionId: \"CONNECT_SESSION\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.connect_api import ConnectApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n connect_api = ConnectApi(api_client)\n response = await connect_api.list_connect_candidates(\n \"CONNECT_SESSION\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/connect-sessions/CONNECT_SESSION/candidates\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "ConnectCandidate": { "type": "object", "properties": { "id": { "type": "string", "description": "Pass it as candidateId to Select Candidate.", "examples": [ "123456789012345" ] }, "platform": { "type": "string", "enum": [ "facebook", "instagram" ] }, "name": { "type": [ "string", "null" ], "examples": [ "Onepostly" ] }, "username": { "type": [ "string", "null" ], "examples": [ "onepostly" ] }, "pictureUrl": { "type": [ "string", "null" ], "examples": [ "https://cdn.onepostly.com/avatars/onepostly.jpg" ] }, "category": { "type": [ "string", "null" ], "description": "Facebook Pages: the Page category.", "examples": [ "Business" ] }, "pageName": { "type": [ "string", "null" ], "description": "Instagram: the Facebook Page the account is linked to.", "examples": [ "Onepostly" ] } }, "required": [ "id", "platform", "name", "username", "pictureUrl", "category", "pageName" ] } }, "parameters": { "SessionId": { "schema": { "type": "string", "minLength": 1, "description": "The connectSession value your redirect URL received.", "examples": [ "cs_eyJhbGciOiJIUzI1NiJ9" ] }, "required": true, "description": "The connectSession value your redirect URL received.", "name": "sessionId", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Select Candidate (/docs/api-reference/connect/select-connect-candidate) Connects the chosen candidate and finishes the connect session. `POST https://api.onepostly.com/v1/connect-sessions/{sessionId}/select` ```json { "paths": { "/v1/connect-sessions/{sessionId}/select": { "post": { "operationId": "selectConnectCandidate", "tags": [ "Connect" ], "summary": "Select candidate", "description": "Connects the chosen candidate and finishes the connect session.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/SessionId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SelectConnectCandidateBody" } } } }, "responses": { "200": { "description": "Connected account", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "account": { "$ref": "#/components/schemas/Account" }, "redirectUrl": { "type": "string", "format": "uri", "description": "Where to send the browser next.", "examples": [ "https://example.com/onepostly/callback?accountId=acc_1699f4157fb643f49d2ac447491f32a8" ] } }, "required": [ "account", "redirectUrl" ] }, "example": { "account": { "id": "acc_1699f4157fb643f49d2ac447491f3204", "platform": "facebook", "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": "Business", "metadata": { "userId": "user_8412" }, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" }, "redirectUrl": "https://yourapp.com/oauth/onepostly?connected=facebook&count=1&accountId=acc_1699f4157fb643f49d2ac447491f3204&handle=yourbrand" } } } }, "400": { "$ref": "#/components/responses/BadRequestReplayable" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The new account needs a payment method, or the payment method could not be set up. The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "This API key is read-only, or the connect session was started by another workspace. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "The candidate is not one this user can connect (PAGE_NOT_FOUND, ACCOUNT_NOT_FOUND). Pick one from List Candidates", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "$ref": "#/components/responses/ConflictReplayable" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, ConnectApi } from \"@onepostly/sdk\";\n\nconst connectApi = new ConnectApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await connectApi.selectConnectCandidate({\n sessionId: \"CONNECT_SESSION\",\n selectConnectCandidateBody: {\n \"candidateId\": \"123456789012345\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.connect_api import ConnectApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n connect_api = ConnectApi(api_client)\n response = await connect_api.select_connect_candidate(\n \"CONNECT_SESSION\",\n select_connect_candidate_body={\n \"candidateId\": \"123456789012345\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/connect-sessions/CONNECT_SESSION/select\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"candidateId\": \"123456789012345\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Account": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "displayName": { "type": "string", "examples": [ "Onepostly" ] }, "handle": { "type": "string", "description": "The account's handle on the platform, without a leading @. LinkedIn has no handles, so a LinkedIn account has its name here.", "examples": [ "onepostly" ] }, "avatarUrl": { "type": [ "string", "null" ], "format": "uri", "examples": [ "https://cdn.onepostly.com/avatars/onepostly.jpg" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "active", "expired", "revoked", "error" ] }, { "type": "string" } ], "description": "active works normally. expired, revoked and error need a reconnect before the account can publish again. expired also covers an authorization that ran out and cannot renew by itself. A disconnected account is no longer returned. The account.disconnected webhook sends it as a DisconnectedAccount. New values can be added, so handle a value you do not know.", "examples": [ "active" ] }, "canAutoRenew": { "type": "boolean", "description": "Whether the authorization renews without the account owner signing in again.", "examples": [ true ] }, "tokenExpiresAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the current authorization expires, or null when it does not.", "examples": [ "2026-12-25T10:00:00.000Z" ] }, "profile": { "type": [ "string", "null" ], "description": "The name of the profile the account is filed under. null when the account is in no profile.", "examples": [ "Business" ] }, "metadata": { "$ref": "#/components/schemas/AccountMetadata", "description": "The metadata sent with the connect that added the account. An empty object when none was sent." }, "xSubscriptionType": { "type": [ "string", "null" ], "description": "X only, such as Premium. The account's X subscription, which sets its post length limit. Null when X does not report it, and left out for other platforms." }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "updatedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "platform", "displayName", "handle", "avatarUrl", "status", "canAutoRenew", "tokenExpiresAt", "profile", "metadata", "createdAt", "updatedAt" ] }, "AccountMetadata": { "type": "object", "additionalProperties": { "type": "string", "maxLength": 500 }, "description": "Your own key-value pairs for the account, such as the id of the user in your app who connected it. Up to 20 keys. Keys are 1 to 40 characters and values up to 500. Do not store secrets here.", "examples": [ { "userId": "user_8412" } ] }, "SelectConnectCandidateBody": { "type": "object", "properties": { "candidateId": { "type": "string", "minLength": 1, "description": "id of a candidate from List Candidates.", "examples": [ "123456789012345" ] }, "redirectUrl": { "type": "string", "format": "uri", "description": "Overrides the session's redirectUrl for the final redirect." } }, "required": [ "candidateId" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "SessionId": { "schema": { "type": "string", "minLength": 1, "description": "The connectSession value your redirect URL received.", "examples": [ "cs_eyJhbGciOiJIUzI1NiJ9" ] }, "required": true, "description": "The connectSession value your redirect URL received.", "name": "sessionId", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ConflictReplayable": { "description": "The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequestReplayable": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Bookmark a Post (/docs/api-reference/engagement/bookmark-post) Bookmarks a post as the account. Supported on X and Bluesky. On X every request is charged to the wallet, a repeat included. `PUT https://api.onepostly.com/v1/accounts/{id}/bookmarks/{postId}` ```json { "paths": { "/v1/accounts/{id}/bookmarks/{postId}": { "put": { "operationId": "bookmarkPost", "tags": [ "Engagement" ], "summary": "Bookmark a post", "description": "Bookmarks a post as the account. Supported on X and Bluesky. On X every request is charged to the wallet, a repeat included.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "1960956321831854280" ] }, "required": true, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "name": "postId", "in": "path" } ], "responses": { "200": { "description": "Bookmark", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Bookmark" }, "example": { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "platform": "bluesky", "bookmarked": true } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), the platform does not support this action (UNSUPPORTED_PLATFORM), or a pst_ postId belongs to another account (POST_ACCOUNT_MISMATCH)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the X action (INSUFFICIENT_WALLET). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND), or no post with this pst_ id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (CONNECTION_INACTIVE, TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, EngagementApi } from \"@onepostly/sdk\";\n\nconst engagementApi = new EngagementApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await engagementApi.bookmarkPost({\n id: \"acc_YOUR_BLUESKY_ACCOUNT_ID\",\n postId: \"at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.engagement_api import EngagementApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n engagement_api = EngagementApi(api_client)\n response = await engagement_api.bookmark_post(\n \"acc_YOUR_BLUESKY_ACCOUNT_ID\",\n \"at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PUT \"https://api.onepostly.com/v1/accounts/acc_YOUR_BLUESKY_ACCOUNT_ID/bookmarks/at%3A%2F%2Fdid%3Aplc%3Az72i7hdynmk6r22z27h6tvur%2Fapp.bsky.feed.post%2F3l6oveex3ii2l\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Bookmark": { "type": "object", "properties": { "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The pst_ id of the post. Use it to undo this action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that acted." }, "platform": { "$ref": "#/components/schemas/Platform" }, "bookmarked": { "type": "boolean", "description": "true after a bookmark, false after the bookmark is removed." } }, "required": [ "postId", "accountId", "platform", "bookmarked" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Like a Post (/docs/api-reference/engagement/like-post) Likes a post as the account. Supported on X, Facebook, YouTube and Bluesky. On X every request is charged to the wallet, a repeat included. `PUT https://api.onepostly.com/v1/accounts/{id}/likes/{postId}` ```json { "paths": { "/v1/accounts/{id}/likes/{postId}": { "put": { "operationId": "likePost", "tags": [ "Engagement" ], "summary": "Like a post", "description": "Likes a post as the account. Supported on X, Facebook, YouTube and Bluesky. On X every request is charged to the wallet, a repeat included.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "1960956321831854280" ] }, "required": true, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "name": "postId", "in": "path" } ], "responses": { "200": { "description": "Like", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Like" }, "example": { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "liked": true } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), the platform does not support this action (UNSUPPORTED_PLATFORM), or a pst_ postId belongs to another account (POST_ACCOUNT_MISMATCH)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the X action (INSUFFICIENT_WALLET). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND), or no post with this pst_ id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (CONNECTION_INACTIVE, TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, EngagementApi } from \"@onepostly/sdk\";\n\nconst engagementApi = new EngagementApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await engagementApi.likePost({\n id: \"acc_YOUR_X_ACCOUNT_ID\",\n postId: \"1960956321831854280\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.engagement_api import EngagementApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n engagement_api = EngagementApi(api_client)\n response = await engagement_api.like_post(\n \"acc_YOUR_X_ACCOUNT_ID\",\n \"1960956321831854280\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PUT \"https://api.onepostly.com/v1/accounts/acc_YOUR_X_ACCOUNT_ID/likes/1960956321831854280\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Like": { "type": "object", "properties": { "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The pst_ id of the post. Use it to undo this action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that acted." }, "platform": { "$ref": "#/components/schemas/Platform" }, "liked": { "type": "boolean", "description": "true after a like, false after the like is removed." } }, "required": [ "postId", "accountId", "platform", "liked" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Reposters (/docs/api-reference/engagement/list-reposters) Lists the accounts that reposted a post. Supported on X and Bluesky. `GET https://api.onepostly.com/v1/posts/{id}/reposts` ```json { "paths": { "/v1/posts/{id}/reposts": { "get": { "operationId": "listReposters", "tags": [ "Engagement" ], "summary": "List reposters", "description": "Lists the accounts that reposted a post. Supported on X and Bluesky.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/PostId" }, { "$ref": "#/components/parameters/Limit50Max100" }, { "$ref": "#/components/parameters/Cursor" } ], "responses": { "200": { "description": "Reposters", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Actor" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "1458203917345619968", "username": "jane_doe", "displayName": "Jane Doe", "avatarUrl": "https://pbs.twimg.com/profile_images/1683325380441128960/yRsRRjGO_normal.jpg" }, { "id": "897451236985471234", "username": "mark_builds", "displayName": "Mark Builds", "avatarUrl": "https://pbs.twimg.com/profile_images/1702113548720128000/Qm4sXk1p_normal.jpg" } ], "nextCursor": null, "hasMore": false } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the platform does not list reposters (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the X action (INSUFFICIENT_WALLET). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No post with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, EngagementApi } from \"@onepostly/sdk\";\n\nconst engagementApi = new EngagementApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await engagementApi.listReposters({\n id: \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.engagement_api import EngagementApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n engagement_api = EngagementApi(api_client)\n response = await engagement_api.list_reposters(\n \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73/reposts\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Actor": { "type": "object", "properties": { "id": { "type": "string", "description": "The platform's id for the user.", "examples": [ "u1" ] }, "username": { "type": [ "string", "null" ], "description": "The user's username, without a leading @. Null when the platform does not share it.", "examples": [ "jane_doe" ] }, "displayName": { "type": [ "string", "null" ], "examples": [ "Jane Doe" ] }, "avatarUrl": { "type": [ "string", "null" ], "examples": [ "https://cdn.onepostly.com/avatars/jane.jpg" ] } }, "required": [ "id", "username", "displayName", "avatarUrl" ] } }, "parameters": { "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max100": { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50, "description": "Items per page. Defaults to 50. Maximum 100.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 100.", "name": "limit", "in": "query" }, "PostId": { "schema": { "type": "string", "minLength": 1, "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Repost a Post (/docs/api-reference/engagement/repost-post) Reposts a post as the account. Supported on X, Threads and Bluesky. On X every request is charged to the wallet, a repeat included. `PUT https://api.onepostly.com/v1/accounts/{id}/reposts/{postId}` ```json { "paths": { "/v1/accounts/{id}/reposts/{postId}": { "put": { "operationId": "repostPost", "tags": [ "Engagement" ], "summary": "Repost a post", "description": "Reposts a post as the account. Supported on X, Threads and Bluesky. On X every request is charged to the wallet, a repeat included.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "1960956321831854280" ] }, "required": true, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "name": "postId", "in": "path" } ], "responses": { "200": { "description": "Repost", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Repost" }, "example": { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "reposted": true, "platformRepostId": "18062934718562044" } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), the platform does not support this action (UNSUPPORTED_PLATFORM), or a pst_ postId belongs to another account (POST_ACCOUNT_MISMATCH)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the X action (INSUFFICIENT_WALLET). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND), or no post with this pst_ id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (CONNECTION_INACTIVE, TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, EngagementApi } from \"@onepostly/sdk\";\n\nconst engagementApi = new EngagementApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await engagementApi.repostPost({\n id: \"acc_YOUR_THREADS_ACCOUNT_ID\",\n postId: \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.engagement_api import EngagementApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n engagement_api = EngagementApi(api_client)\n response = await engagement_api.repost_post(\n \"acc_YOUR_THREADS_ACCOUNT_ID\",\n \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PUT \"https://api.onepostly.com/v1/accounts/acc_YOUR_THREADS_ACCOUNT_ID/reposts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Repost": { "type": "object", "properties": { "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The pst_ id of the post. Use it to undo this action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that acted." }, "platform": { "$ref": "#/components/schemas/Platform" }, "reposted": { "type": "boolean", "description": "true after a repost, false after the repost is undone." }, "platformRepostId": { "type": [ "string", "null" ], "description": "The repost's own id on the platform, when the platform reports one." } }, "required": [ "postId", "accountId", "platform", "reposted", "platformRepostId" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Remove a Bookmark (/docs/api-reference/engagement/unbookmark-post) Remove a bookmark the account made. Name the post as you did to bookmark it, or by the postId the response returned. On X every request is charged to the wallet, a repeat included. `DELETE https://api.onepostly.com/v1/accounts/{id}/bookmarks/{postId}` ```json { "paths": { "/v1/accounts/{id}/bookmarks/{postId}": { "delete": { "operationId": "unbookmarkPost", "tags": [ "Engagement" ], "summary": "Remove a bookmark", "description": "Remove a bookmark the account made. Name the post as you did to bookmark it, or by the postId the response returned. On X every request is charged to the wallet, a repeat included.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "1960956321831854280" ] }, "required": true, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "name": "postId", "in": "path" } ], "responses": { "200": { "description": "Bookmark removed", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Bookmark" }, "example": { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "bookmarked": false } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), the platform does not support this action (UNSUPPORTED_PLATFORM), or a pst_ postId belongs to another account (POST_ACCOUNT_MISMATCH)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the X action (INSUFFICIENT_WALLET). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND), or no post with this pst_ id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (CONNECTION_INACTIVE, TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, EngagementApi } from \"@onepostly/sdk\";\n\nconst engagementApi = new EngagementApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await engagementApi.unbookmarkPost({\n id: \"acc_YOUR_X_ACCOUNT_ID\",\n postId: \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.engagement_api import EngagementApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n engagement_api = EngagementApi(api_client)\n response = await engagement_api.unbookmark_post(\n \"acc_YOUR_X_ACCOUNT_ID\",\n \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/accounts/acc_YOUR_X_ACCOUNT_ID/bookmarks/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Bookmark": { "type": "object", "properties": { "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The pst_ id of the post. Use it to undo this action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that acted." }, "platform": { "$ref": "#/components/schemas/Platform" }, "bookmarked": { "type": "boolean", "description": "true after a bookmark, false after the bookmark is removed." } }, "required": [ "postId", "accountId", "platform", "bookmarked" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Remove a Like (/docs/api-reference/engagement/unlike-post) Remove a like the account made. Name the post as you did to like it, or by the postId the response returned. On X every request is charged to the wallet, a repeat included. `DELETE https://api.onepostly.com/v1/accounts/{id}/likes/{postId}` ```json { "paths": { "/v1/accounts/{id}/likes/{postId}": { "delete": { "operationId": "unlikePost", "tags": [ "Engagement" ], "summary": "Remove a like", "description": "Remove a like the account made. Name the post as you did to like it, or by the postId the response returned. On X every request is charged to the wallet, a repeat included.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "1960956321831854280" ] }, "required": true, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "name": "postId", "in": "path" } ], "responses": { "200": { "description": "Like removed", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Like" }, "example": { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_YOUTUBE_ACCOUNT_ID", "platform": "youtube", "liked": false } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), the platform does not support this action (UNSUPPORTED_PLATFORM), or a pst_ postId belongs to another account (POST_ACCOUNT_MISMATCH)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the X action (INSUFFICIENT_WALLET). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND), or no post with this pst_ id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (CONNECTION_INACTIVE, TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, EngagementApi } from \"@onepostly/sdk\";\n\nconst engagementApi = new EngagementApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await engagementApi.unlikePost({\n id: \"acc_YOUR_YOUTUBE_ACCOUNT_ID\",\n postId: \"dQw4w9WgXcQ\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.engagement_api import EngagementApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n engagement_api = EngagementApi(api_client)\n response = await engagement_api.unlike_post(\n \"acc_YOUR_YOUTUBE_ACCOUNT_ID\",\n \"dQw4w9WgXcQ\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/accounts/acc_YOUR_YOUTUBE_ACCOUNT_ID/likes/dQw4w9WgXcQ\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Like": { "type": "object", "properties": { "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The pst_ id of the post. Use it to undo this action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that acted." }, "platform": { "$ref": "#/components/schemas/Platform" }, "liked": { "type": "boolean", "description": "true after a like, false after the like is removed." } }, "required": [ "postId", "accountId", "platform", "liked" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Undo a Repost (/docs/api-reference/engagement/unrepost-post) Undo a repost the account made. Name the post as you did to repost it, or by the postId the response returned. On X every request is charged to the wallet, a repeat included. `DELETE https://api.onepostly.com/v1/accounts/{id}/reposts/{postId}` ```json { "paths": { "/v1/accounts/{id}/reposts/{postId}": { "delete": { "operationId": "unrepostPost", "tags": [ "Engagement" ], "summary": "Undo a repost", "description": "Undo a repost the account made. Name the post as you did to repost it, or by the postId the response returned. On X every request is charged to the wallet, a repeat included.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "1960956321831854280" ] }, "required": true, "description": "The post. Send the pst_ id of one of this account's posts, or the platform's own id of any post on the account's platform. Percent-encode it in the URL, as the SDKs do, so a Bluesky at:// URI is sent as at%3A%2F%2F…", "name": "postId", "in": "path" } ], "responses": { "200": { "description": "Repost removed", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Repost" }, "example": { "postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "reposted": false, "platformRepostId": null } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), the platform does not support this action (UNSUPPORTED_PLATFORM), or a pst_ postId belongs to another account (POST_ACCOUNT_MISMATCH)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the X action (INSUFFICIENT_WALLET). The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND), or no post with this pst_ id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not live on its platform yet (NOT_PUBLISHED), or the account must be reconnected (CONNECTION_INACTIVE, TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, EngagementApi } from \"@onepostly/sdk\";\n\nconst engagementApi = new EngagementApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await engagementApi.unrepostPost({\n id: \"acc_YOUR_THREADS_ACCOUNT_ID\",\n postId: \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.engagement_api import EngagementApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n engagement_api = EngagementApi(api_client)\n response = await engagement_api.unrepost_post(\n \"acc_YOUR_THREADS_ACCOUNT_ID\",\n \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/accounts/acc_YOUR_THREADS_ACCOUNT_ID/reposts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Repost": { "type": "object", "properties": { "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The pst_ id of the post. Use it to undo this action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that acted." }, "platform": { "$ref": "#/components/schemas/Platform" }, "reposted": { "type": "boolean", "description": "true after a repost, false after the repost is undone." }, "platformRepostId": { "type": [ "string", "null" ], "description": "The repost's own id on the platform, when the platform reports one." } }, "required": [ "postId", "accountId", "platform", "reposted", "platformRepostId" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Messenger Profile (/docs/api-reference/facebook/get-messenger-profile) Returns the ice breakers and persistent menu of a Facebook Page's Messenger. `GET https://api.onepostly.com/v1/accounts/{id}/messenger-profile` ```json { "paths": { "/v1/accounts/{id}/messenger-profile": { "get": { "operationId": "getMessengerProfile", "tags": [ "Accounts" ], "summary": "Get Messenger profile", "description": "Returns the ice breakers and persistent menu of a Facebook Page's Messenger.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" } ], "responses": { "200": { "description": "Messenger profile", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessengerProfile" }, "example": { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "iceBreakers": [ { "question": "What are your opening hours?", "payload": "HOURS" }, { "question": "Do you deliver?", "payload": "DELIVERY" } ], "persistentMenu": [ { "type": "web_url", "title": "Order online", "url": "https://example.com/order", "payload": null } ] } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not a Facebook Page (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.getMessengerProfile({\n id: \"acc_YOUR_FACEBOOK_ACCOUNT_ID\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.get_messenger_profile(\n \"acc_YOUR_FACEBOOK_ACCOUNT_ID\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/messenger-profile\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "MessengerProfile": { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "iceBreakers": { "type": "array", "items": { "type": "object", "properties": { "question": { "type": "string", "description": "Question shown when a conversation starts." }, "payload": { "type": "string", "description": "Value sent to the Page when the question is tapped." } }, "required": [ "question", "payload" ] }, "description": "Questions shown when a conversation starts." }, "persistentMenu": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "web_url", "postback" ], "description": "web_url opens url. postback sends payload to the Page." }, "title": { "type": "string", "description": "Text shown on the menu item." }, "url": { "type": [ "string", "null" ], "description": "Link a web_url item opens. Null otherwise." }, "payload": { "type": [ "string", "null" ], "description": "Value a postback item sends. Null otherwise." } }, "required": [ "type", "title", "url", "payload" ] }, "description": "Menu items shown in every conversation." } }, "required": [ "accountId", "iceBreakers", "persistentMenu" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Conflict": { "description": "The account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Page Reviews (/docs/api-reference/facebook/list-account-reviews) Lists the reviews of a Facebook Page, newest first. `GET https://api.onepostly.com/v1/accounts/{id}/reviews` ```json { "paths": { "/v1/accounts/{id}/reviews": { "get": { "operationId": "listAccountReviews", "tags": [ "Accounts" ], "summary": "List Page reviews", "description": "Lists the reviews of a Facebook Page, newest first.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "$ref": "#/components/parameters/Limit50Max50" }, { "$ref": "#/components/parameters/Cursor" } ], "responses": { "200": { "description": "Reviews", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/PageReview" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "1093847561029384", "recommendation": "positive", "rating": null, "text": "Friendly staff and the best sourdough in the neighborhood.", "reviewerName": "Jane Doe", "createdAt": "2027-03-14T16:20:00.000Z" }, { "id": "1093847561027710", "recommendation": "negative", "rating": null, "text": "Waited 20 minutes for a coffee on Saturday.", "reviewerName": null, "createdAt": "2027-03-09T11:05:00.000Z" }, { "id": "1093847561015526", "recommendation": null, "rating": 5, "text": null, "reviewerName": "Sam Lee", "createdAt": "2018-06-02T08:45:00.000Z" } ], "nextCursor": "QVFIUjRtNWdLbGd6UXBVZAk1jY0FfTnJ3dkx2S0RxZAXhOQmZAPNnV5dE1CSmVvUHg", "hasMore": true } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not a Facebook Page (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.listAccountReviews({\n id: \"acc_YOUR_FACEBOOK_ACCOUNT_ID\",\n limit: 20,\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.list_account_reviews(\n \"acc_YOUR_FACEBOOK_ACCOUNT_ID\",\n limit=20,\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/reviews?limit=20\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "PageReview": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "1234567890" ] }, "recommendation": { "type": [ "string", "null" ], "enum": [ "positive", "negative", null ], "description": "Whether the reviewer recommends the Page. `null` on older star-only reviews.", "examples": [ "positive" ] }, "rating": { "type": [ "number", "null" ], "description": "The legacy 1 to 5 star rating. `null` on reviews without stars.", "examples": [ 5 ] }, "text": { "type": [ "string", "null" ], "description": "The review text. Null for a review without text.", "examples": [ "Great service!" ] }, "reviewerName": { "type": [ "string", "null" ], "description": "The reviewer's name. Null when Facebook does not share it.", "examples": [ "Jane Doe" ] }, "createdAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the review was posted. Null when Facebook does not report it.", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "recommendation", "rating", "text", "reviewerName", "createdAt" ] } }, "parameters": { "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max50": { "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 50, "description": "Items per page. Defaults to 50. Maximum 50.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 50.", "name": "limit", "in": "query" }, "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Conflict": { "description": "The account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Set Messenger Profile (/docs/api-reference/facebook/set-messenger-profile) Replaces the ice breakers and persistent menu of a Facebook Page's Messenger. A field you leave out keeps its current value. `PUT https://api.onepostly.com/v1/accounts/{id}/messenger-profile` ```json { "paths": { "/v1/accounts/{id}/messenger-profile": { "put": { "operationId": "setMessengerProfile", "tags": [ "Accounts" ], "summary": "Set Messenger profile", "description": "Replaces the ice breakers and persistent menu of a Facebook Page's Messenger. A field you leave out keeps its current value.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetMessengerProfileBody" } } } }, "responses": { "200": { "description": "Updated Messenger profile", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessengerProfile" }, "example": { "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "iceBreakers": [ { "question": "What are your opening hours?", "payload": "HOURS" }, { "question": "Do you deliver?", "payload": "DELIVERY" } ], "persistentMenu": [ { "type": "web_url", "title": "Order online", "url": "https://example.com/order", "payload": null } ] } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not a Facebook Page (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.setMessengerProfile({\n id: \"acc_YOUR_FACEBOOK_ACCOUNT_ID\",\n setMessengerProfileBody: {\n \"iceBreakers\": [\n {\n \"question\": \"What are your opening hours?\",\n \"payload\": \"HOURS\"\n },\n {\n \"question\": \"Do you deliver?\",\n \"payload\": \"DELIVERY\"\n }\n ],\n \"persistentMenu\": [\n {\n \"type\": \"web_url\",\n \"title\": \"Order online\",\n \"url\": \"https://example.com/order\"\n }\n ]\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.set_messenger_profile(\n \"acc_YOUR_FACEBOOK_ACCOUNT_ID\",\n set_messenger_profile_body={\n \"iceBreakers\": [\n {\n \"question\": \"What are your opening hours?\",\n \"payload\": \"HOURS\"\n },\n {\n \"question\": \"Do you deliver?\",\n \"payload\": \"DELIVERY\"\n }\n ],\n \"persistentMenu\": [\n {\n \"type\": \"web_url\",\n \"title\": \"Order online\",\n \"url\": \"https://example.com/order\"\n }\n ]\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PUT \"https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/messenger-profile\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"iceBreakers\": [\n {\n \"question\": \"What are your opening hours?\",\n \"payload\": \"HOURS\"\n },\n {\n \"question\": \"Do you deliver?\",\n \"payload\": \"DELIVERY\"\n }\n ],\n \"persistentMenu\": [\n {\n \"type\": \"web_url\",\n \"title\": \"Order online\",\n \"url\": \"https://example.com/order\"\n }\n ]\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "MessengerProfile": { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "iceBreakers": { "type": "array", "items": { "type": "object", "properties": { "question": { "type": "string", "description": "Question shown when a conversation starts." }, "payload": { "type": "string", "description": "Value sent to the Page when the question is tapped." } }, "required": [ "question", "payload" ] }, "description": "Questions shown when a conversation starts." }, "persistentMenu": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "web_url", "postback" ], "description": "web_url opens url. postback sends payload to the Page." }, "title": { "type": "string", "description": "Text shown on the menu item." }, "url": { "type": [ "string", "null" ], "description": "Link a web_url item opens. Null otherwise." }, "payload": { "type": [ "string", "null" ], "description": "Value a postback item sends. Null otherwise." } }, "required": [ "type", "title", "url", "payload" ] }, "description": "Menu items shown in every conversation." } }, "required": [ "accountId", "iceBreakers", "persistentMenu" ] }, "SetMessengerProfileBody": { "type": "object", "properties": { "iceBreakers": { "type": "array", "items": { "type": "object", "properties": { "question": { "type": "string", "minLength": 1, "maxLength": 80, "description": "Question shown when a conversation starts, up to 80 characters." }, "payload": { "type": "string", "minLength": 1, "maxLength": 1000, "description": "Value sent to the Page when the question is tapped, up to 1,000 characters." } }, "required": [ "question", "payload" ] }, "maxItems": 4, "description": "Up to 4 questions shown when a conversation starts." }, "persistentMenu": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "web_url", "postback" ], "description": "web_url opens url. postback sends payload to the Page." }, "title": { "type": "string", "minLength": 1, "maxLength": 20, "description": "Text shown on the menu item, up to 20 characters." }, "url": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link a web_url item opens. Required for web_url." }, "payload": { "type": "string", "minLength": 1, "maxLength": 1000, "description": "Value a postback item sends, up to 1,000 characters. Required for postback." } }, "required": [ "type", "title" ] }, "maxItems": 3, "description": "Up to 3 menu items. web_url items need url, postback items need payload." } } } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Conflict": { "description": "The account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # API Overview (/docs/api-reference) {/* Generated by generate-api-docs.mjs from the public OpenAPI spec. Do not edit by hand. */} Use these pages to look up every endpoint's parameters, request body, responses and SDK samples. ## Base URL [#base-url] ``` https://api.onepostly.com ``` ## Authentication [#authentication] Send your API key as a bearer token in the `Authorization` header. See [Create an API Key](/docs/authentication#create-an-api-key). ```bash curl https://api.onepostly.com/v1/accounts \ -H "Authorization: Bearer $ONEPOSTLY_API_KEY" ``` ## Errors and Rate Limits [#errors-and-rate-limits] Error responses share one envelope with a stable code. See [Error Codes](/docs/error-handling#error-codes) and [Handle 429 Responses](/docs/rate-limits#handle-429-responses). ## Endpoints [#endpoints] ### Core [#core] - [Accounts](/docs/api-reference/accounts/list-accounts): 8 endpoints. List, reconnect and disconnect accounts, and read their stats and recent media. - [Connect](/docs/api-reference/connect/create-connect-session): 3 endpoints. Let your users connect their accounts with the platform's own sign-in. - [Profiles](/docs/api-reference/profiles/list-profiles): 4 endpoints. Group accounts into named profiles. ### Publishing [#publishing] - [Posts](/docs/api-reference/posts/list-posts): 6 endpoints. Create, schedule, edit and delete posts, and sync posts made on the platform. - [Media](/docs/api-reference/media/list-media): 4 endpoints. Upload images, videos and documents for your posts. - [Analytics](/docs/api-reference/analytics/get-post-analytics): 3 endpoints. Read post metrics, daily timelines and account insights. ### Engagement [#engagement] - [Comments](/docs/api-reference/comments/list-comments): 9 endpoints. List, reply to, hide, like and delete comments. - [Likes and Reposts](/docs/api-reference/engagement/unlike-post): 7 endpoints. Like, repost and bookmark posts as one of your accounts. - [Messages](/docs/api-reference/messages/list-conversations): 5 endpoints. Read and send direct messages on Instagram, Facebook and Bluesky. - [Automations](/docs/api-reference/automations/list-automations): 5 endpoints. Answer comments and messages that match a keyword with a direct message. ### Platform APIs [#platform-apis] - [Instagram](/docs/api-reference/instagram/search-account-audio): 1 endpoint. Search Instagram audio for reels. - [Facebook](/docs/api-reference/facebook/list-account-reviews): 3 endpoints. Read Page reviews and set the Messenger profile of a Facebook Page. - [TikTok](/docs/api-reference/tiktok/get-creator-info): 1 endpoint. Read TikTok creator info before posting. - [Pinterest](/docs/api-reference/pinterest/list-account-boards): 2 endpoints. List and create Pinterest boards. - [Bluesky](/docs/api-reference/bluesky/get-account-settings): 2 endpoints. Read and update Bluesky account settings. ### Developer [#developer] - [Webhooks](/docs/api-reference/webhooks/list-webhook-event-types): 11 endpoints. Create and manage webhook endpoints and inspect their deliveries. - [Webhook Events](/docs/api-reference/webhook-events/post-scheduled): 30 events. Every event your webhook endpoints receive, with its headers and payload. - [Wallet](/docs/api-reference/wallet/get-wallet-balance): 1 endpoint. Read the wallet balance that pays for X actions. # Search Instagram Audio (/docs/api-reference/instagram/search-account-audio) Searches Instagram's audio catalog as the account. Without q it returns trending audio. Needs an Instagram account connected with loginMethod facebook_login. `GET https://api.onepostly.com/v1/accounts/{id}/audio` ```json { "paths": { "/v1/accounts/{id}/audio": { "get": { "operationId": "searchAccountAudio", "tags": [ "Accounts" ], "summary": "Search Instagram audio", "description": "Searches Instagram's audio catalog as the account. Without q it returns trending audio. Needs an Instagram account connected with loginMethod facebook_login.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Search text." }, "required": false, "description": "Search text.", "name": "q", "in": "query" }, { "schema": { "type": "string", "enum": [ "music", "original_sound" ], "description": "Type of audio. Defaults to music.", "examples": [ "music" ] }, "required": false, "description": "Type of audio. Defaults to music.", "name": "type", "in": "query" }, { "$ref": "#/components/parameters/Limit20Max20" } ], "responses": { "200": { "description": "Audio tracks", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/AudioTrack" } } }, "required": [ "data" ] }, "example": { "data": [ { "id": "587784541076604", "title": "Summer Nights", "artist": "Lena Hart", "coverUrl": "https://scontent.xx.fbcdn.net/v/t39.30808-6/summer-nights.jpg", "previewUrl": "https://video.xx.fbcdn.net/v/t42.1790-2/summer-nights.m4a", "durationSec": 168 }, { "id": "1043529871264118", "title": "Summer Drive", "artist": "The Coastliners", "coverUrl": "https://scontent.xx.fbcdn.net/v/t39.30808-6/summer-drive.jpg", "previewUrl": "https://video.xx.fbcdn.net/v/t42.1790-2/summer-drive.m4a", "durationSec": 201 }, { "id": "829104563378215", "title": "Endless Summer", "artist": "Mira Sol", "coverUrl": "https://scontent.xx.fbcdn.net/v/t39.30808-6/endless-summer.jpg", "previewUrl": "https://video.xx.fbcdn.net/v/t42.1790-2/endless-summer.m4a", "durationSec": 145 } ] } } } }, "400": { "description": "The request is invalid, or the Instagram account was not connected with loginMethod facebook_login (VALIDATION_ERROR). An account that is not on Instagram returns UNSUPPORTED_PLATFORM", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.searchAccountAudio({\n id: \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n q: \"summer\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.search_account_audio(\n \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n q=\"summer\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_INSTAGRAM_ACCOUNT_ID/audio?q=summer\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "AudioTrack": { "type": "object", "properties": { "id": { "type": "string", "description": "Pass it as instagram.audioId when you publish a reel.", "examples": [ "1234567890" ] }, "title": { "type": [ "string", "null" ], "examples": [ "Summer song" ] }, "artist": { "type": [ "string", "null" ], "examples": [ "The Band" ] }, "coverUrl": { "type": [ "string", "null" ], "description": "Cover art URL. Null when Instagram does not report one." }, "previewUrl": { "type": [ "string", "null" ], "description": "URL of a short preview of the track. Null when Instagram does not report one." }, "durationSec": { "type": [ "number", "null" ], "description": "Track length, in seconds. Null when Instagram does not report it.", "examples": [ 30 ] } }, "required": [ "id", "title", "artist", "coverUrl", "previewUrl", "durationSec" ] } }, "parameters": { "Limit20Max20": { "schema": { "type": "integer", "minimum": 1, "maximum": 20, "default": 20, "description": "Items per page. Defaults to 20. Maximum 20.", "examples": [ 20 ] }, "required": false, "description": "Items per page. Defaults to 20. Maximum 20.", "name": "limit", "in": "query" }, "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Conflict": { "description": "The account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Create Media (/docs/api-reference/media/create-media) Creates a media asset and returns uploadUrl. PUT the file to uploadUrl with the declared Content-Type and exactly size bytes, then use the asset's id in a post. Files are kept for 7 days until a post uses them. `POST https://api.onepostly.com/v1/media` ```json { "paths": { "/v1/media": { "post": { "operationId": "createMedia", "tags": [ "Media" ], "summary": "Create media", "description": "Creates a media asset and returns uploadUrl. PUT the file to uploadUrl with the declared Content-Type and exactly size bytes, then use the asset's id in a post. Files are kept for 7 days until a post uses them.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateMediaBody" } } } }, "responses": { "201": { "description": "Media asset waiting for its upload", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreatedMedia" }, "example": { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b", "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a0b.mp4", "contentType": "video/mp4", "sizeBytes": null, "filename": "launch.mp4", "status": "pending", "createdAt": "2027-03-15T09:00:00.000Z", "uploadUrl": "https://5d1e8a3c9f2b4e7a.r2.cloudflarestorage.com/onepostly-media/temp/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a0b.mp4?X-Amz-Expires=3600&X-Amz-Date=20270315T090000Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=EXAMPLEKEY%2F20270315%2Fauto%2Fs3%2Faws4_request&X-Amz-SignedHeaders=content-length%3Bcontent-type%3Bhost&X-Amz-Signature=0f4c2b9e7a1d3f5b8c6e0a2d4f6b8e1c3a5d7f9b2e4c6a8d0f1b3e5c7a9d2f4b", "uploadExpiresIn": 3600 } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), contentType is not a supported file type (UNSUPPORTED_MEDIA_TYPE), or size is over the limit for contentType (MEDIA_TOO_LARGE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "409": { "$ref": "#/components/responses/ConflictReplayable" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "503": { "description": "The service is temporarily unavailable (SERVICE_UNAVAILABLE). Try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, MediaApi } from \"@onepostly/sdk\";\n\nconst mediaApi = new MediaApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await mediaApi.createMedia({\n createMediaBody: {\n \"filename\": \"launch.mp4\",\n \"contentType\": \"video/mp4\",\n \"size\": 48203776\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.media_api import MediaApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n media_api = MediaApi(api_client)\n response = await media_api.create_media(\n create_media_body={\n \"filename\": \"launch.mp4\",\n \"contentType\": \"video/mp4\",\n \"size\": 48203776\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/media\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"filename\": \"launch.mp4\",\n \"contentType\": \"video/mp4\",\n \"size\": 48203776\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "CreatedMedia": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" ], "description": "Pass it in a post's media as { id }." }, "url": { "type": "string", "format": "uri", "description": "Public URL of the file. It never changes, and serves the file once status is ready.", "examples": [ "https://cdn.onepostly.com/media/WORKSPACE_ID/MEDIA_ID.jpg" ] }, "contentType": { "type": "string", "description": "MIME type of the file.", "examples": [ "image/jpeg" ] }, "sizeBytes": { "type": [ "integer", "null" ], "description": "File size in bytes. Null until status is ready.", "examples": [ 12345 ] }, "filename": { "type": [ "string", "null" ], "description": "The filename sent to Create Media. Null for a file added without one.", "examples": [ "photo.jpg" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "pending", "ready" ] }, { "type": "string" } ], "description": "pending until the file has been uploaded to uploadUrl and checked, usually within seconds. New values can be added, so handle a value you do not know.", "examples": [ "ready" ] }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "uploadUrl": { "type": "string", "format": "uri", "description": "Upload the file here with a PUT request, the declared Content-Type and exactly size bytes. No API key is needed for the upload.", "examples": [ "https://myaccount.r2.cloudflarestorage.com/temp/1699f415.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=3600" ] }, "uploadExpiresIn": { "type": "integer", "description": "Seconds until uploadUrl expires.", "examples": [ 3600 ] } }, "required": [ "id", "url", "contentType", "sizeBytes", "filename", "status", "createdAt", "uploadUrl", "uploadExpiresIn" ] }, "CreateMediaBody": { "type": "object", "properties": { "filename": { "type": "string", "minLength": 1, "maxLength": 255, "description": "Name of the file you will upload.", "examples": [ "photo.jpg" ] }, "contentType": { "type": "string", "minLength": 1, "maxLength": 127, "description": "MIME type of the file. Send the same value as the Content-Type header of the upload.", "examples": [ "image/jpeg" ] }, "size": { "type": "integer", "exclusiveMinimum": 0, "maximum": 1073741824, "description": "Exact size of the file in bytes. The upload must be exactly this many bytes, and within the size limit for contentType.", "examples": [ 482113 ] } }, "required": [ "filename", "contentType", "size" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ConflictReplayable": { "description": "The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Delete Media (/docs/api-reference/media/delete-media) Deletes a media asset and its file. Posts already published with it stay on the platform. `DELETE https://api.onepostly.com/v1/media/{id}` ```json { "paths": { "/v1/media/{id}": { "delete": { "operationId": "deleteMedia", "tags": [ "Media" ], "summary": "Delete media", "description": "Deletes a media asset and its file. Posts already published with it stay on the platform.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/MediaId" } ], "responses": { "204": { "description": "Deleted", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No media asset with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, MediaApi } from \"@onepostly/sdk\";\n\nconst mediaApi = new MediaApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await mediaApi.deleteMedia({\n id: \"med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.media_api import MediaApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n media_api = MediaApi(api_client)\n response = await media_api.delete_media(\n \"med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/media/med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] } }, "parameters": { "MediaId": { "schema": { "type": "string", "minLength": 1, "examples": [ "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Media (/docs/api-reference/media/get-media) Returns one media asset. status turns ready once the upload has arrived. `GET https://api.onepostly.com/v1/media/{id}` ```json { "paths": { "/v1/media/{id}": { "get": { "operationId": "getMedia", "tags": [ "Media" ], "summary": "Get media", "description": "Returns one media asset. status turns ready once the upload has arrived.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/MediaId" } ], "responses": { "200": { "description": "Media asset", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MediaAsset" }, "example": { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b", "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a0b.mp4", "contentType": "video/mp4", "sizeBytes": 48203776, "filename": "launch.mp4", "status": "ready", "createdAt": "2027-03-15T09:00:00.000Z" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No media asset with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, MediaApi } from \"@onepostly/sdk\";\n\nconst mediaApi = new MediaApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await mediaApi.getMedia({\n id: \"med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.media_api import MediaApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n media_api = MediaApi(api_client)\n response = await media_api.get_media(\n \"med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/media/med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "MediaAsset": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" ], "description": "Pass it in a post's media as { id }." }, "url": { "type": "string", "format": "uri", "description": "Public URL of the file. It never changes, and serves the file once status is ready.", "examples": [ "https://cdn.onepostly.com/media/WORKSPACE_ID/MEDIA_ID.jpg" ] }, "contentType": { "type": "string", "description": "MIME type of the file.", "examples": [ "image/jpeg" ] }, "sizeBytes": { "type": [ "integer", "null" ], "description": "File size in bytes. Null until status is ready.", "examples": [ 12345 ] }, "filename": { "type": [ "string", "null" ], "description": "The filename sent to Create Media. Null for a file added without one.", "examples": [ "photo.jpg" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "pending", "ready" ] }, { "type": "string" } ], "description": "pending until the file has been uploaded to uploadUrl and checked, usually within seconds. New values can be added, so handle a value you do not know.", "examples": [ "ready" ] }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "url", "contentType", "sizeBytes", "filename", "status", "createdAt" ] } }, "parameters": { "MediaId": { "schema": { "type": "string", "minLength": 1, "examples": [ "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Media (/docs/api-reference/media/list-media) Lists the workspace's uploaded media, newest first. `GET https://api.onepostly.com/v1/media` ```json { "paths": { "/v1/media": { "get": { "operationId": "listMedia", "tags": [ "Media" ], "summary": "List media", "description": "Lists the workspace's uploaded media, newest first.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/Limit50Max100" }, { "$ref": "#/components/parameters/Cursor" }, { "$ref": "#/components/parameters/Include" } ], "responses": { "200": { "description": "Media", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/MediaAsset" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." }, "total": { "type": "integer", "description": "Items matching the filters across every page. Present when include has total." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b", "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a0b.mp4", "contentType": "video/mp4", "sizeBytes": 48203776, "filename": "launch.mp4", "status": "ready", "createdAt": "2027-03-15T09:00:00.000Z" }, { "id": "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a02", "url": "https://cdn.onepostly.com/media/5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b/7f3a9c2e-1b4d-4e8f-9a6b-5c4d3e2f1a02.jpg", "contentType": "image/jpeg", "sizeBytes": 482113, "filename": "spring.jpg", "status": "ready", "createdAt": "2027-03-14T16:30:00.000Z" } ], "nextCursor": null, "hasMore": false } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, MediaApi } from \"@onepostly/sdk\";\n\nconst mediaApi = new MediaApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await mediaApi.listMedia({\n limit: 20,\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.media_api import MediaApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n media_api = MediaApi(api_client)\n response = await media_api.list_media(\n limit=20,\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/media?limit=20\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "MediaAsset": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" ], "description": "Pass it in a post's media as { id }." }, "url": { "type": "string", "format": "uri", "description": "Public URL of the file. It never changes, and serves the file once status is ready.", "examples": [ "https://cdn.onepostly.com/media/WORKSPACE_ID/MEDIA_ID.jpg" ] }, "contentType": { "type": "string", "description": "MIME type of the file.", "examples": [ "image/jpeg" ] }, "sizeBytes": { "type": [ "integer", "null" ], "description": "File size in bytes. Null until status is ready.", "examples": [ 12345 ] }, "filename": { "type": [ "string", "null" ], "description": "The filename sent to Create Media. Null for a file added without one.", "examples": [ "photo.jpg" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "pending", "ready" ] }, { "type": "string" } ], "description": "pending until the file has been uploaded to uploadUrl and checked, usually within seconds. New values can be added, so handle a value you do not know.", "examples": [ "ready" ] }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "url", "contentType", "sizeBytes", "filename", "status", "createdAt" ] } }, "parameters": { "Include": { "schema": { "type": "string", "description": "Comma-separated extras to add to the response: total." }, "required": false, "description": "Comma-separated extras to add to the response: total.", "name": "include", "in": "query" }, "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max100": { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50, "description": "Items per page. Defaults to 50. Maximum 100.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 100.", "name": "limit", "in": "query" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Create Conversation (/docs/api-reference/messages/create-conversation) Starts a one-to-one conversation. On Instagram and Facebook it can be read once it has a message. Supported on Bluesky, Instagram and Facebook. `POST https://api.onepostly.com/v1/accounts/{id}/conversations` ```json { "paths": { "/v1/accounts/{id}/conversations": { "post": { "operationId": "createConversation", "tags": [ "Inbox" ], "summary": "Create conversation", "description": "Starts a one-to-one conversation. On Instagram and Facebook it can be read once it has a message. Supported on Bluesky, Instagram and Facebook.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateConversationBody" } } } }, "responses": { "201": { "description": "Conversation", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conversation" }, "example": { "id": "cnv_xZWwUFsb6q2nrlD7GUiqQxNHfiqbgdNAjqlcvDLTpafW1UHpqYkJAIRnqf5uJ71zS3gigSZp", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "members": [ { "id": "did:plc:4y7hqd2kz3rbe6mfxw5tnc2a", "username": "yourbrand.bsky.social", "displayName": "Your Brand" }, { "id": "did:plc:z72i7hdynmk6r22z27h6tvur", "username": "alice.bsky.social", "displayName": "Alice" } ], "muted": false, "unreadCount": 0, "lastMessage": null } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not on Bluesky, Instagram or Facebook (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND), or the platform has no such recipient (RECIPIENT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The recipient cannot receive messages from the account (RECIPIENT_UNREACHABLE), or the account must be reconnected (CONNECTION_INACTIVE, CONNECTION_BROKEN, TOKEN_EXPIRED, TOKEN_INVALID). The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "description": "The account was connected without messaging access (INBOX_PERMISSION, PERMISSION_DENIED). Reconnect it and grant messaging access", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, InboxApi } from \"@onepostly/sdk\";\n\nconst inboxApi = new InboxApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await inboxApi.createConversation({\n id: \"acc_YOUR_BLUESKY_ACCOUNT_ID\",\n createConversationBody: {\n \"recipient\": \"alice.bsky.social\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.inbox_api import InboxApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n inbox_api = InboxApi(api_client)\n response = await inbox_api.create_conversation(\n \"acc_YOUR_BLUESKY_ACCOUNT_ID\",\n create_conversation_body={\n \"recipient\": \"alice.bsky.social\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/accounts/acc_YOUR_BLUESKY_ACCOUNT_ID/conversations\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"recipient\": \"alice.bsky.social\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Conversation": { "type": "object", "properties": { "id": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "members": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "The platform's id for the member.", "examples": [ "did:plc:alice" ] }, "username": { "type": [ "string", "null" ], "description": "The member's username. Null when the platform does not share it.", "examples": [ "alice.bsky.social" ] }, "displayName": { "type": [ "string", "null" ], "description": "The member's display name. Null when the platform does not share it.", "examples": [ "Alice" ] } }, "required": [ "id", "username", "displayName" ] }, "description": "The people in the conversation." }, "muted": { "type": "boolean", "description": "Bluesky: true when the account muted the conversation. Always false on Instagram and Facebook." }, "unreadCount": { "type": "integer", "description": "Messages the account has not read yet. 0 when the platform does not report it.", "examples": [ 2 ] }, "lastMessage": { "type": [ "object", "null" ], "properties": { "id": { "type": "string", "description": "The platform's id for the message." }, "text": { "type": [ "string", "null" ], "description": "The message text. Null for a message with only attachments.", "examples": [ "Hey!" ] }, "sentAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the message was sent. Null when the platform does not report it.", "examples": [ "2026-09-08T12:00:00.000Z" ] } }, "required": [ "id", "text", "sentAt" ], "description": "The newest message. Null when the platform does not include it in the list." } }, "required": [ "id", "accountId", "members", "muted", "unreadCount", "lastMessage" ] }, "CreateConversationBody": { "type": "object", "properties": { "recipient": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Who to message: a Bluesky handle or DID, an Instagram username or user id, or a Facebook page-scoped user id.", "examples": [ "alice.bsky.social" ] } }, "required": [ "recipient" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Conversation (/docs/api-reference/messages/get-conversation) Supported on Bluesky, Instagram and Facebook. `GET https://api.onepostly.com/v1/accounts/{id}/conversations/{conversationId}` ```json { "paths": { "/v1/accounts/{id}/conversations/{conversationId}": { "get": { "operationId": "getConversation", "tags": [ "Inbox" ], "summary": "Get conversation", "description": "Supported on Bluesky, Instagram and Facebook.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "$ref": "#/components/parameters/ConversationId" } ], "responses": { "200": { "description": "Conversation", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conversation" }, "example": { "id": "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "members": [ { "id": "did:plc:4kq7n2xhv3wbzmd5ltc6jy2e", "username": "yourbrand.bsky.social", "displayName": "Your Brand" }, { "id": "did:plc:r2vx6hzk3m7nqa4yc5dwtb8j", "username": "alice.bsky.social", "displayName": "Alice" } ], "muted": false, "unreadCount": 1, "lastMessage": { "id": "3lkr4w2m7xs2c", "text": "Hey, loved your latest post!", "sentAt": "2027-03-15T15:20:41.000Z" } } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not on Bluesky, Instagram or Facebook (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND), or the account has no conversation with this id (CONVO_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The account must be reconnected (CONNECTION_INACTIVE, CONNECTION_BROKEN, TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "description": "The account was connected without messaging access (INBOX_PERMISSION, PERMISSION_DENIED). Reconnect it and grant messaging access", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, InboxApi } from \"@onepostly/sdk\";\n\nconst inboxApi = new InboxApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await inboxApi.getConversation({\n id: \"acc_YOUR_BLUESKY_ACCOUNT_ID\",\n conversationId: \"cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.inbox_api import InboxApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n inbox_api = InboxApi(api_client)\n response = await inbox_api.get_conversation(\n \"acc_YOUR_BLUESKY_ACCOUNT_ID\",\n \"cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_BLUESKY_ACCOUNT_ID/conversations/cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Conversation": { "type": "object", "properties": { "id": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "members": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "The platform's id for the member.", "examples": [ "did:plc:alice" ] }, "username": { "type": [ "string", "null" ], "description": "The member's username. Null when the platform does not share it.", "examples": [ "alice.bsky.social" ] }, "displayName": { "type": [ "string", "null" ], "description": "The member's display name. Null when the platform does not share it.", "examples": [ "Alice" ] } }, "required": [ "id", "username", "displayName" ] }, "description": "The people in the conversation." }, "muted": { "type": "boolean", "description": "Bluesky: true when the account muted the conversation. Always false on Instagram and Facebook." }, "unreadCount": { "type": "integer", "description": "Messages the account has not read yet. 0 when the platform does not report it.", "examples": [ 2 ] }, "lastMessage": { "type": [ "object", "null" ], "properties": { "id": { "type": "string", "description": "The platform's id for the message." }, "text": { "type": [ "string", "null" ], "description": "The message text. Null for a message with only attachments.", "examples": [ "Hey!" ] }, "sentAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the message was sent. Null when the platform does not report it.", "examples": [ "2026-09-08T12:00:00.000Z" ] } }, "required": [ "id", "text", "sentAt" ], "description": "The newest message. Null when the platform does not include it in the list." } }, "required": [ "id", "accountId", "members", "muted", "unreadCount", "lastMessage" ] } }, "parameters": { "ConversationId": { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook. It only works in the workspace that received it.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "required": true, "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook. It only works in the workspace that received it.", "name": "conversationId", "in": "path" }, "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Conversations (/docs/api-reference/messages/list-conversations) Lists the account's direct message conversations, most recent first. Supported on Bluesky, Instagram and Facebook. `GET https://api.onepostly.com/v1/accounts/{id}/conversations` ```json { "paths": { "/v1/accounts/{id}/conversations": { "get": { "operationId": "listConversations", "tags": [ "Inbox" ], "summary": "List conversations", "description": "Lists the account's direct message conversations, most recent first. Supported on Bluesky, Instagram and Facebook.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "$ref": "#/components/parameters/Limit50Max100" }, { "$ref": "#/components/parameters/Cursor" } ], "responses": { "200": { "description": "Conversations", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Conversation" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "cnv_u1rTltEvz7pEbzpQOLjQAlMVsqWCdakS9U2wjAFB6CV6SYgY3Bx8GTrVhAn9njOg3eB2YWHX", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "members": [ { "id": "17841401234567890", "username": "yourbrand", "displayName": "yourbrand" }, { "id": "6873452198765432", "username": "jane_doe", "displayName": "jane_doe" } ], "muted": false, "unreadCount": 0, "lastMessage": { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM2NDEyOTg3NjU0MzIxMDk4NzY1NDMy", "text": "Do you ship to Canada?", "sentAt": "2027-03-15T11:42:08.000Z" } }, { "id": "cnv_UYeVH71CtvWwPasNAhEA9WXmVPAMJhQLmnGMapF5MxmPu59aNUBxoHt0T0YnAq98AujCL19c", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "members": [ { "id": "17841401234567890", "username": "yourbrand", "displayName": "yourbrand" }, { "id": "7120984456321987", "username": "mark.builds", "displayName": "mark.builds" } ], "muted": false, "unreadCount": 0, "lastMessage": { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM1MzQ1Njc4OTAxMjM0NTY3ODkwMTIz", "text": "Thanks, it arrived today!", "sentAt": "2027-03-15T10:17:45.000Z" } } ], "nextCursor": null, "hasMore": false } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not on Bluesky, Instagram or Facebook (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "description": "The account must be reconnected (CONNECTION_INACTIVE, CONNECTION_BROKEN, TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "description": "The account was connected without messaging access (INBOX_PERMISSION, PERMISSION_DENIED). Reconnect it and grant messaging access", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, InboxApi } from \"@onepostly/sdk\";\n\nconst inboxApi = new InboxApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await inboxApi.listConversations({\n id: \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.inbox_api import InboxApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n inbox_api = InboxApi(api_client)\n response = await inbox_api.list_conversations(\n \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_INSTAGRAM_ACCOUNT_ID/conversations\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Conversation": { "type": "object", "properties": { "id": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "members": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "The platform's id for the member.", "examples": [ "did:plc:alice" ] }, "username": { "type": [ "string", "null" ], "description": "The member's username. Null when the platform does not share it.", "examples": [ "alice.bsky.social" ] }, "displayName": { "type": [ "string", "null" ], "description": "The member's display name. Null when the platform does not share it.", "examples": [ "Alice" ] } }, "required": [ "id", "username", "displayName" ] }, "description": "The people in the conversation." }, "muted": { "type": "boolean", "description": "Bluesky: true when the account muted the conversation. Always false on Instagram and Facebook." }, "unreadCount": { "type": "integer", "description": "Messages the account has not read yet. 0 when the platform does not report it.", "examples": [ 2 ] }, "lastMessage": { "type": [ "object", "null" ], "properties": { "id": { "type": "string", "description": "The platform's id for the message." }, "text": { "type": [ "string", "null" ], "description": "The message text. Null for a message with only attachments.", "examples": [ "Hey!" ] }, "sentAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the message was sent. Null when the platform does not report it.", "examples": [ "2026-09-08T12:00:00.000Z" ] } }, "required": [ "id", "text", "sentAt" ], "description": "The newest message. Null when the platform does not include it in the list." } }, "required": [ "id", "accountId", "members", "muted", "unreadCount", "lastMessage" ] } }, "parameters": { "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max100": { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50, "description": "Items per page. Defaults to 50. Maximum 100.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 100.", "name": "limit", "in": "query" }, "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Messages (/docs/api-reference/messages/list-messages) Lists the messages of a conversation, newest first. Supported on Bluesky, Instagram and Facebook. `GET https://api.onepostly.com/v1/accounts/{id}/conversations/{conversationId}/messages` ```json { "paths": { "/v1/accounts/{id}/conversations/{conversationId}/messages": { "get": { "operationId": "listMessages", "tags": [ "Inbox" ], "summary": "List messages", "description": "Lists the messages of a conversation, newest first. Supported on Bluesky, Instagram and Facebook.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "$ref": "#/components/parameters/ConversationId" }, { "$ref": "#/components/parameters/Limit50Max100" }, { "$ref": "#/components/parameters/Cursor" } ], "responses": { "200": { "description": "Messages", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Message" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM2NDEyOTg3NjU0MzIxMDk4NzY1NDMy", "conversationId": "cnv_YOUR_CONVERSATION_ID", "text": "Do you ship to Canada?", "senderId": "6873452198765432", "sentAt": "2027-03-15T11:42:08.000Z", "attachments": [] }, { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM2NDEyOTg3NjU0MzIxMDk4NzY1NDE5", "conversationId": "cnv_YOUR_CONVERSATION_ID", "text": "Yes, it is in stock in every size.", "senderId": "17841401234567890", "sentAt": "2027-03-15T11:40:02.000Z", "attachments": [] }, { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM2NDEyOTg3NjU0MzIxMDk4NzY1NDA3", "conversationId": "cnv_YOUR_CONVERSATION_ID", "text": "Hi! Is this jacket still available?", "senderId": "6873452198765432", "sentAt": "2027-03-15T11:38:40.000Z", "attachments": [] }, { "id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM2NDEyOTg3NjU0MzIxMDk4NzY1Mzk1", "conversationId": "cnv_YOUR_CONVERSATION_ID", "text": null, "senderId": "6873452198765432", "sentAt": "2027-03-15T11:38:15.000Z", "attachments": [ { "type": "image", "url": "https://lookaside.fbsbx.com/ig_messaging_cdn/?asset_id=18043219876543210&signature=AbxQ3kLm9pRtYv2WcZ8sN1" } ] } ], "nextCursor": null, "hasMore": false } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not on Bluesky, Instagram or Facebook (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND), or the account has no conversation with this id (CONVO_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The account must be reconnected (CONNECTION_INACTIVE, CONNECTION_BROKEN, TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "description": "The account was connected without messaging access (INBOX_PERMISSION, PERMISSION_DENIED). Reconnect it and grant messaging access", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, InboxApi } from \"@onepostly/sdk\";\n\nconst inboxApi = new InboxApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await inboxApi.listMessages({\n id: \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n conversationId: \"cnv_YOUR_CONVERSATION_ID\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.inbox_api import InboxApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n inbox_api = InboxApi(api_client)\n response = await inbox_api.list_messages(\n \"acc_YOUR_INSTAGRAM_ACCOUNT_ID\",\n \"cnv_YOUR_CONVERSATION_ID\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_INSTAGRAM_ACCOUNT_ID/conversations/cnv_YOUR_CONVERSATION_ID/messages\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Message": { "type": "object", "properties": { "id": { "type": "string", "description": "The platform's id for the message." }, "conversationId": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "text": { "type": [ "string", "null" ], "description": "The message text. Null for a message with only attachments.", "examples": [ "Hey, loved your latest post!" ] }, "senderId": { "type": "string", "description": "The platform's id for the sender.", "examples": [ "did:plc:alice" ] }, "sentAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the message was sent. Null when the platform does not report it.", "examples": [ "2026-09-08T12:00:00.000Z" ] }, "attachments": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "image", "video", "audio", "file", "other" ], "description": "What the attachment is. other is a kind the platform does not name." }, "url": { "type": [ "string", "null" ], "description": "URL of the attachment. Null when the platform does not share one." } }, "required": [ "type", "url" ] }, "description": "Instagram and Facebook: media attached to the message." } }, "required": [ "id", "conversationId", "text", "senderId", "sentAt", "attachments" ] } }, "parameters": { "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max100": { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50, "description": "Items per page. Defaults to 50. Maximum 100.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 100.", "name": "limit", "in": "query" }, "ConversationId": { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook. It only works in the workspace that received it.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "required": true, "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook. It only works in the workspace that received it.", "name": "conversationId", "in": "path" }, "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Send Message (/docs/api-reference/messages/send-message) Sends a message in a conversation. Instagram and Facebook also take attachments, quick replies, buttons and cards, within 24 hours of the person's last message. Supported on Bluesky, Instagram and Facebook. `POST https://api.onepostly.com/v1/accounts/{id}/conversations/{conversationId}/messages` ```json { "paths": { "/v1/accounts/{id}/conversations/{conversationId}/messages": { "post": { "operationId": "sendMessage", "tags": [ "Inbox" ], "summary": "Send message", "description": "Sends a message in a conversation. Instagram and Facebook also take attachments, quick replies, buttons and cards, within 24 hours of the person's last message. Supported on Bluesky, Instagram and Facebook.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "$ref": "#/components/parameters/ConversationId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SendMessageBody" } } } }, "responses": { "201": { "description": "Sent message", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Message" }, "example": { "id": "m_Xq2b7KfRz1nT8vLp3sWcYd9GhJ0aMeU4oQiN5kB6xZtVrHlF2gDsAy7wEcP1uOjI3mK8nL", "conversationId": "cnv_YOUR_CONVERSATION_ID", "text": "Yes, we deliver on Sundays from 10:00 to 14:00.", "senderId": "104987654321098", "sentAt": "2027-03-15T12:05:31.000Z", "attachments": [] } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR, TEXT_REQUIRED, TEXT_TOO_LONG, INVALID_ATTACHMENT, INVALID_TEMPLATE), the account's platform takes no attachments, quick replies or templates (ATTACHMENT_UNSUPPORTED, TEMPLATE_UNSUPPORTED), or the account is not on Bluesky, Instagram or Facebook (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND), or the account has no conversation with this id (CONVO_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The 24-hour messaging window has closed (MESSAGE_WINDOW_EXPIRED), the recipient cannot receive messages (RECIPIENT_UNREACHABLE), the conversation is locked (CONVO_LOCKED), or the account must be reconnected (CONNECTION_INACTIVE, CONNECTION_BROKEN, TOKEN_EXPIRED, TOKEN_INVALID). The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "description": "The account was connected without messaging access (INBOX_PERMISSION, PERMISSION_DENIED). Reconnect it and grant messaging access", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, InboxApi } from \"@onepostly/sdk\";\n\nconst inboxApi = new InboxApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await inboxApi.sendMessage({\n id: \"acc_YOUR_FACEBOOK_ACCOUNT_ID\",\n conversationId: \"cnv_YOUR_CONVERSATION_ID\",\n sendMessageBody: {\n \"text\": \"Yes, we deliver on Sundays from 10:00 to 14:00.\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.inbox_api import InboxApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n inbox_api = InboxApi(api_client)\n response = await inbox_api.send_message(\n \"acc_YOUR_FACEBOOK_ACCOUNT_ID\",\n \"cnv_YOUR_CONVERSATION_ID\",\n send_message_body={\n \"text\": \"Yes, we deliver on Sundays from 10:00 to 14:00.\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/accounts/acc_YOUR_FACEBOOK_ACCOUNT_ID/conversations/cnv_YOUR_CONVERSATION_ID/messages\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"text\": \"Yes, we deliver on Sundays from 10:00 to 14:00.\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Message": { "type": "object", "properties": { "id": { "type": "string", "description": "The platform's id for the message." }, "conversationId": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "text": { "type": [ "string", "null" ], "description": "The message text. Null for a message with only attachments.", "examples": [ "Hey, loved your latest post!" ] }, "senderId": { "type": "string", "description": "The platform's id for the sender.", "examples": [ "did:plc:alice" ] }, "sentAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the message was sent. Null when the platform does not report it.", "examples": [ "2026-09-08T12:00:00.000Z" ] }, "attachments": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "image", "video", "audio", "file", "other" ], "description": "What the attachment is. other is a kind the platform does not name." }, "url": { "type": [ "string", "null" ], "description": "URL of the attachment. Null when the platform does not share one." } }, "required": [ "type", "url" ] }, "description": "Instagram and Facebook: media attached to the message." } }, "required": [ "id", "conversationId", "text", "senderId", "sentAt", "attachments" ] }, "SendMessageBody": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 2000, "description": "The message text, up to 1,000 characters on Bluesky, 1,000 on Instagram and 2,000 on Facebook. A longer text returns TEXT_TOO_LONG.", "examples": [ "Hey, loved your latest post!" ] }, "attachmentUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Instagram and Facebook: public HTTPS URL of an image, video, audio file or PDF to attach. Cannot be combined with buttons or cards." }, "quickReplies": { "type": "array", "items": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 20, "description": "Text on the quick reply, up to 20 characters.", "examples": [ "Red" ] }, "payload": { "type": "string", "minLength": 1, "maxLength": 1000, "description": "Value sent back when the quick reply is tapped, up to 1,000 characters.", "examples": [ "PICK_RED" ] }, "imageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Icon shown on the quick reply." } }, "required": [ "title", "payload" ] }, "maxItems": 13, "description": "Instagram and Facebook: quick reply buttons under the message." }, "buttons": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "web_url", "postback" ], "description": "web_url opens url. postback sends payload back." }, "title": { "type": "string", "minLength": 1, "maxLength": 20, "description": "Text on the button, up to 20 characters.", "examples": [ "View Website" ] }, "url": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Required for web_url buttons." }, "payload": { "type": "string", "minLength": 1, "maxLength": 1000, "description": "Required for postback buttons." } }, "required": [ "type", "title" ] }, "maxItems": 3, "description": "Instagram and Facebook: buttons shown with the message." }, "cards": { "type": "array", "items": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 80, "description": "Card title, up to 80 characters.", "examples": [ "Welcome!" ] }, "subtitle": { "type": "string", "minLength": 1, "maxLength": 80, "description": "Text under the title, up to 80 characters." }, "imageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Card image URL." }, "buttons": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "web_url", "postback" ], "description": "web_url opens url. postback sends payload back." }, "title": { "type": "string", "minLength": 1, "maxLength": 20, "description": "Text on the button, up to 20 characters.", "examples": [ "View Website" ] }, "url": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Required for web_url buttons." }, "payload": { "type": "string", "minLength": 1, "maxLength": 1000, "description": "Required for postback buttons." } }, "required": [ "type", "title" ] }, "maxItems": 3, "description": "Up to 3 buttons on the card." } }, "required": [ "title" ] }, "maxItems": 10, "description": "Instagram and Facebook: cards shown as a swipeable carousel." } }, "required": [ "text" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "ConversationId": { "schema": { "type": "string", "minLength": 1, "maxLength": 512, "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook. It only works in the workspace that received it.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "required": true, "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook. It only works in the workspace that received it.", "name": "conversationId", "in": "path" }, "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Create Pinterest Board (/docs/api-reference/pinterest/create-account-board) `POST https://api.onepostly.com/v1/accounts/{id}/boards` ```json { "paths": { "/v1/accounts/{id}/boards": { "post": { "operationId": "createAccountBoard", "tags": [ "Accounts" ], "summary": "Create Pinterest board", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreatePinterestBoardBody" } } } }, "responses": { "201": { "description": "Created board", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PinterestBoard" }, "example": { "id": "1035968376946032587", "name": "Weeknight Dinners", "isDefault": false } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not a Pinterest account (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "$ref": "#/components/responses/NotFoundReplayable" }, "409": { "description": "The account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID). The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefusedReplayable" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.createAccountBoard({\n id: \"acc_YOUR_PINTEREST_ACCOUNT_ID\",\n createPinterestBoardBody: {\n \"name\": \"Weeknight Dinners\",\n \"description\": \"Quick recipes for busy evenings\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.create_account_board(\n \"acc_YOUR_PINTEREST_ACCOUNT_ID\",\n create_pinterest_board_body={\n \"name\": \"Weeknight Dinners\",\n \"description\": \"Quick recipes for busy evenings\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/accounts/acc_YOUR_PINTEREST_ACCOUNT_ID/boards\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"name\": \"Weeknight Dinners\",\n \"description\": \"Quick recipes for busy evenings\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "PinterestBoard": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "1234567890123456789" ] }, "name": { "type": "string", "examples": [ "Summer ideas" ] }, "isDefault": { "type": "boolean", "description": "The account's suggested board, a sensible preselection in a picker. A post still names its board in pinterest.boardId.", "examples": [ true ] } }, "required": [ "id", "name", "isDefault" ] }, "CreatePinterestBoardBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 180, "description": "Board name, up to 180 characters.", "examples": [ "Summer ideas" ] }, "description": { "type": "string", "maxLength": 500, "description": "Board description, up to 500 characters.", "examples": [ "My summer inspiration board" ] } }, "required": [ "name" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefusedReplayable": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFoundReplayable": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Pinterest Boards (/docs/api-reference/pinterest/list-account-boards) Lists the Pinterest boards the account can publish pins to. `GET https://api.onepostly.com/v1/accounts/{id}/boards` ```json { "paths": { "/v1/accounts/{id}/boards": { "get": { "operationId": "listAccountBoards", "tags": [ "Accounts" ], "summary": "List Pinterest boards", "description": "Lists the Pinterest boards the account can publish pins to.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" } ], "responses": { "200": { "description": "Boards", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/PinterestBoard" } } }, "required": [ "data" ] }, "example": { "data": [ { "id": "1035968376946032411", "name": "Recipes", "isDefault": true }, { "id": "1035968376946032398", "name": "Kitchen Ideas", "isDefault": false }, { "id": "1035968376946032405", "name": "Meal Prep", "isDefault": false } ] } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not a Pinterest account (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.listAccountBoards({\n id: \"acc_YOUR_PINTEREST_ACCOUNT_ID\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.list_account_boards(\n \"acc_YOUR_PINTEREST_ACCOUNT_ID\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_PINTEREST_ACCOUNT_ID/boards\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "PinterestBoard": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "1234567890123456789" ] }, "name": { "type": "string", "examples": [ "Summer ideas" ] }, "isDefault": { "type": "boolean", "description": "The account's suggested board, a sensible preselection in a picker. A post still names its board in pinterest.boardId.", "examples": [ true ] } }, "required": [ "id", "name", "isDefault" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Conflict": { "description": "The account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Create Post (/docs/api-reference/posts/create-post) Publishes or schedules a post on one or more accounts. Each account gets its own post, and the posts of one request share a groupId. If any account cannot take the post, nothing is created. `POST https://api.onepostly.com/v1/posts` ```json { "paths": { "/v1/posts": { "post": { "operationId": "createPost", "tags": [ "Posts" ], "summary": "Create post", "description": "Publishes or schedules a post on one or more accounts. Each account gets its own post, and the posts of one request share a groupId. If any account cannot take the post, nothing is created.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreatePostBody" } } } }, "responses": { "201": { "description": "Created posts", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreatedPosts" }, "example": { "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "publishing", "text": "New release notes are up.", "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" }, { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_BLUESKY_ACCOUNT_ID", "platform": "bluesky", "source": "onepostly", "status": "publishing", "text": "New release notes are up.", "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" } ] } } } }, "400": { "$ref": "#/components/responses/BadRequestReplayable" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover the request's X posts (INSUFFICIENT_WALLET). Every X account is counted, and a thread is charged once for each of its posts. Nothing is created. The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "description": "An account in accounts is not connected to the workspace (ACCOUNT_NOT_FOUND), or a media id names no uploaded file (MEDIA_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "An account must be reconnected (CONNECTION_INACTIVE), or quotePostId or replyToPostId names a post that is not live on its platform (POST_NOT_PUBLISHED). An Idempotency-Key already used for a different request returns IDEMPOTENCY_KEY_REUSED, and one whose first request is still running returns IDEMPOTENCY_KEY_IN_USE", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, PostsApi } from \"@onepostly/sdk\";\n\nconst postsApi = new PostsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await postsApi.createPost({\n createPostBody: {\n \"text\": \"New release notes are up.\",\n \"accounts\": [\n {\n \"accountId\": \"acc_YOUR_X_ACCOUNT_ID\"\n },\n {\n \"accountId\": \"acc_YOUR_BLUESKY_ACCOUNT_ID\"\n }\n ]\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.posts_api import PostsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n posts_api = PostsApi(api_client)\n response = await posts_api.create_post(\n create_post_body={\n \"text\": \"New release notes are up.\",\n \"accounts\": [\n {\n \"accountId\": \"acc_YOUR_X_ACCOUNT_ID\"\n },\n {\n \"accountId\": \"acc_YOUR_BLUESKY_ACCOUNT_ID\"\n }\n ]\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/posts\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"text\": \"New release notes are up.\",\n \"accounts\": [\n {\n \"accountId\": \"acc_YOUR_X_ACCOUNT_ID\"\n },\n {\n \"accountId\": \"acc_YOUR_BLUESKY_ACCOUNT_ID\"\n }\n ]\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "CreatedPosts": { "type": "object", "properties": { "groupId": { "type": "string", "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ] }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Post" } } }, "required": [ "groupId", "data" ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." }, "CreatePostBody": { "type": "object", "properties": { "text": { "type": "string", "maxLength": 63206, "default": "", "description": "The post text. Each account's platform limit applies, such as 500 characters on Threads. A longer text returns VALIDATION_ERROR.", "examples": [ "Ship day" ] }, "mediaKind": { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ], "description": "What the media is. Optional for text posts and for one image, video or document, where the file shows its kind. Required for stories and for a Facebook reel. On Instagram, video and reel both publish a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaRef" }, "maxItems": 35, "default": [], "description": "Media files, in order. Each platform's own cap on the number of files applies." }, "thread": { "type": "array", "items": { "$ref": "#/components/schemas/ThreadItemInput" }, "minItems": 1, "maxItems": 25, "description": "X, Threads and Bluesky. Posts published as replies under the first one, in order." }, "scheduledFor": { "type": "string", "minLength": 1, "maxLength": 32, "description": "Local date and time to publish, such as 2027-03-15T09:00:00, without Z or an offset. Omit it to publish now." }, "timezone": { "type": "string", "minLength": 1, "maxLength": 64, "description": "IANA timezone of scheduledFor, such as America/New_York. Defaults to UTC." }, "accounts": { "type": "array", "items": { "$ref": "#/components/schemas/AccountTarget" }, "minItems": 1, "maxItems": 50, "description": "Accounts to publish to, up to 50. Each account gets its own post." } }, "required": [ "accounts" ], "additionalProperties": false }, "AccountTarget": { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "An account id from List Accounts." }, "text": { "type": "string", "maxLength": 63206, "description": "Text for this account only. Defaults to the post text." }, "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "required": [ "accountId" ], "additionalProperties": false, "description": "One account to publish to. Platform options go under the account's platform key, such as tiktok for a TikTok account." }, "ThreadItemInput": { "type": "object", "properties": { "text": { "type": "string", "maxLength": 63206, "default": "", "description": "Text of the reply. Each account's platform limit applies.", "examples": [ "Second post of the thread" ] }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaRef" }, "maxItems": 20, "default": [], "description": "Media files of the reply, in order." } }, "additionalProperties": false }, "MediaRef": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" ], "description": "A media asset uploaded with Create Media." }, "url": { "type": "string", "maxLength": 2048, "format": "uri", "description": "A public HTTPS URL of the file.", "examples": [ "https://cdn.onepostly.com/media/product.jpg" ] } }, "additionalProperties": false, "description": "A media file: send id or url." } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequestReplayable": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Delete Post (/docs/api-reference/posts/delete-post) Cancels a post that has not been published yet, or deletes a published post from the platform, all posts of its thread included. The post stays in Onepostly with status cancelled or deleted. Deleting an X post is charged to the wallet. `DELETE https://api.onepostly.com/v1/posts/{id}` ```json { "paths": { "/v1/posts/{id}": { "delete": { "operationId": "deletePost", "tags": [ "Posts" ], "summary": "Delete post", "description": "Cancels a post that has not been published yet, or deletes a published post from the platform, all posts of its thread included. The post stays in Onepostly with status cancelled or deleted. Deleting an X post is charged to the wallet.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/PostId" } ], "responses": { "200": { "description": "The cancelled or deleted post", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Post" }, "example": { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "source": "onepostly", "status": "deleted", "text": "New release notes are up.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "104987654321098_122134567890123456", "url": "https://www.facebook.com/yourbrand/posts/pfbid02Xk8c7rFqZJ1nT5sV9wYbLmQe3hGdR6uAoPiK4zCxN2", "error": null, "publishedAt": "2027-03-15T09:00:04.000Z", "metrics": { "impressions": 1234, "reach": 987, "likes": 123, "comments": 12, "shares": 4, "saves": null, "views": 456, "engagement": 139 }, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-16T09:00:00.000Z" } } } }, "400": { "description": "The platform cannot delete this post through the API (UNSUPPORTED_PLATFORM). TikTok posts are one example", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The wallet cannot cover deleting an X post (INSUFFICIENT_WALLET). A thread is charged once for each of its posts. The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No post with this id (NOT_FOUND), or the post's account is no longer connected (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post cannot be deleted (NOT_DELETABLE) because it was published outside Onepostly or failed before reaching the platform. The post may also be publishing right now (POST_PUBLISHING), or the account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, PostsApi } from \"@onepostly/sdk\";\n\nconst postsApi = new PostsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await postsApi.deletePost({\n id: \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.posts_api import PostsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n posts_api = PostsApi(api_client)\n response = await posts_api.delete_post(\n \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." } }, "parameters": { "PostId": { "schema": { "type": "string", "minLength": 1, "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Post (/docs/api-reference/posts/get-post) `GET https://api.onepostly.com/v1/posts/{id}` ```json { "paths": { "/v1/posts/{id}": { "get": { "operationId": "getPost", "tags": [ "Posts" ], "summary": "Get post", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/PostId" } ], "responses": { "200": { "description": "Post", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Post" }, "example": { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_FACEBOOK_ACCOUNT_ID", "platform": "facebook", "source": "onepostly", "status": "published", "text": "New release notes are up.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "104987654321098_122134567890123456", "url": "https://www.facebook.com/yourbrand/posts/pfbid02Xk8c7rFqZJ1nT5sV9wYbLmQe3hGdR6uAoPiK4zCxN2", "error": null, "publishedAt": "2027-03-15T09:00:04.000Z", "metrics": { "impressions": 1234, "reach": 987, "likes": 123, "comments": 12, "shares": 4, "saves": null, "views": 456, "engagement": 139 }, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No post with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, PostsApi } from \"@onepostly/sdk\";\n\nconst postsApi = new PostsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await postsApi.getPost({\n id: \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.posts_api import PostsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n posts_api = PostsApi(api_client)\n response = await posts_api.get_post(\n \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." } }, "parameters": { "PostId": { "schema": { "type": "string", "minLength": 1, "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Posts (/docs/api-reference/posts/list-posts) Lists the workspace's posts, newest first: posts made through Onepostly, and posts the accounts made on the platform that a sync found. `GET https://api.onepostly.com/v1/posts` ```json { "paths": { "/v1/posts": { "get": { "operationId": "listPosts", "tags": [ "Posts" ], "summary": "List posts", "description": "Lists the workspace's posts, newest first: posts made through Onepostly, and posts the accounts made on the platform that a sync found.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/Limit50Max100" }, { "$ref": "#/components/parameters/Cursor" }, { "schema": { "type": "string", "description": "Comma-separated statuses to include, such as scheduled,published. Any of scheduled, publishing, published, failed, cancelled, deleted." }, "required": false, "description": "Comma-separated statuses to include, such as scheduled,published. Any of scheduled, publishing, published, failed, cancelled, deleted.", "name": "status", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Only posts on this platform.", "examples": [ "instagram" ] }, "required": false, "description": "Only posts on this platform.", "name": "platform", "in": "query" }, { "schema": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "Only posts of this account." }, "required": false, "description": "Only posts of this account.", "name": "accountId", "in": "query" }, { "schema": { "type": "string", "maxLength": 60, "description": "Only posts of accounts filed under the profile with this name. Letter case does not matter. Use none for accounts without a profile.", "examples": [ "Business" ] }, "required": false, "description": "Only posts of accounts filed under the profile with this name. Letter case does not matter. Use none for accounts without a profile.", "name": "profile", "in": "query" }, { "schema": { "type": "string", "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Only the posts one Create Post request made." }, "required": false, "description": "Only the posts one Create Post request made.", "name": "groupId", "in": "query" }, { "schema": { "type": "string", "enum": [ "onepostly", "external" ], "description": "onepostly for posts made through Onepostly, external for posts made on the platform." }, "required": false, "description": "onepostly for posts made through Onepostly, external for posts made on the platform.", "name": "source", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "Only posts dated at or after this time. A post's date is its schedule, else its publish time, else its creation time." }, "required": false, "description": "Only posts dated at or after this time. A post's date is its schedule, else its publish time, else its creation time.", "name": "since", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "Only posts dated before this time." }, "required": false, "description": "Only posts dated before this time.", "name": "until", "in": "query" }, { "schema": { "type": "string", "enum": [ "created_desc", "created_asc", "published_desc", "published_asc", "scheduled_desc", "scheduled_asc", "metric:engagement", "metric:likes", "metric:comments", "metric:shares", "metric:views", "metric:impressions", "metric:reach", "metric:saves" ], "description": "Order of the list. Defaults to created_desc. metric: ranks measured posts by a lifetime metric, highest first." }, "required": false, "description": "Order of the list. Defaults to created_desc. metric: ranks measured posts by a lifetime metric, highest first.", "name": "sort", "in": "query" }, { "schema": { "type": "string", "description": "Comma-separated extras to add to the response: total, facets." }, "required": false, "description": "Comma-separated extras to add to the response: total, facets.", "name": "include", "in": "query" } ], "responses": { "200": { "description": "Posts", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Post" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." }, "total": { "type": "integer", "description": "Posts matching the filters. Present when include has total." }, "facets": { "$ref": "#/components/schemas/PostFacets" } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a02", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e02", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "scheduled", "text": "Our summer collection drops next week.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/summer.jpg" } ], "thread": [], "scheduledFor": "2027-03-20T09:00:00", "timezone": "America/New_York", "options": {}, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T10:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" }, { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "published", "text": "Our spring collection is live.", "mediaKind": "image", "media": [ { "url": "https://cdn.onepostly.com/media/spring.jpg" } ], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "17895695668004550", "url": "https://www.instagram.com/p/DHb7x2ySk4N/", "error": null, "publishedAt": "2027-03-15T09:00:04.000Z", "metrics": { "impressions": 1234, "reach": 987, "likes": 123, "comments": 12, "shares": 4, "saves": 2, "views": 1234, "engagement": 141 }, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:04.000Z" } ], "nextCursor": null, "hasMore": false } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, PostsApi } from \"@onepostly/sdk\";\n\nconst postsApi = new PostsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await postsApi.listPosts({\n limit: 20,\n status: \"scheduled,published\",\n platform: \"instagram\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.posts_api import PostsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n posts_api = PostsApi(api_client)\n response = await posts_api.list_posts(\n limit=20,\n status=\"scheduled,published\",\n platform=\"instagram\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/posts?limit=20&status=scheduled%2Cpublished&platform=instagram\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "PostFacets": { "type": "object", "properties": { "status": { "type": "array", "items": { "type": "object", "properties": { "status": { "$ref": "#/components/schemas/PostStatus" }, "count": { "type": "integer" } }, "required": [ "status", "count" ] } }, "platform": { "type": "array", "items": { "type": "object", "properties": { "platform": { "type": "string" }, "count": { "type": "integer" } }, "required": [ "platform", "count" ] } } }, "required": [ "status", "platform" ], "description": "Post counts per status and per platform. Each ignores its own filter. Present when include has facets." }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] } }, "parameters": { "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max100": { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50, "description": "Items per page. Defaults to 50. Maximum 100.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 100.", "name": "limit", "in": "query" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Sync Account Posts (/docs/api-reference/posts/sync-account-posts) Finds posts the account published on the platform, outside Onepostly, and adds them to your posts with source external. Send url or platformPostId to find one post, or neither to sync the account's 20 most recent posts. `POST https://api.onepostly.com/v1/accounts/{id}/sync` ```json { "paths": { "/v1/accounts/{id}/sync": { "post": { "operationId": "syncAccountPosts", "tags": [ "Posts" ], "summary": "Sync account posts", "description": "Finds posts the account published on the platform, outside Onepostly, and adds them to your posts with source external. Send url or platformPostId to find one post, or neither to sync the account's 20 most recent posts.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SyncAccountPostsBody" } } } }, "responses": { "200": { "description": "Synced posts", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Post" }, "description": "The account's recent posts, or the one post that was found. Empty when a url or platformPostId matched nothing among the 20 most recent posts." }, "skipped": { "type": "boolean", "description": "true when the account was synced in the last 15 seconds, so only posts Onepostly already knows are returned." } }, "required": [ "data", "skipped" ] }, "example": { "data": [ { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": null, "accountId": "acc_YOUR_THREADS_ACCOUNT_ID", "platform": "threads", "source": "external", "status": "published", "text": null, "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "18047285913046723", "url": "https://www.threads.com/@yourbrand/post/DbNQAb8ABC1", "error": null, "publishedAt": "2027-03-14T18:30:00.000Z", "metrics": null, "createdAt": "2027-03-15T10:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } ], "skipped": false } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), for example when it sends both url and platformPostId, or the platform has no post sync (UNSUPPORTED_PLATFORM). LinkedIn and Pinterest accounts cannot be synced", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "$ref": "#/components/responses/NotFoundReplayable" }, "409": { "description": "The account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID). The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "$ref": "#/components/responses/PlatformRefusedReplayable" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, PostsApi } from \"@onepostly/sdk\";\n\nconst postsApi = new PostsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await postsApi.syncAccountPosts({\n id: \"acc_YOUR_THREADS_ACCOUNT_ID\",\n syncAccountPostsBody: {\n \"url\": \"https://www.threads.com/@yourbrand/post/DbNQAb8ABC1\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.posts_api import PostsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n posts_api = PostsApi(api_client)\n response = await posts_api.sync_account_posts(\n \"acc_YOUR_THREADS_ACCOUNT_ID\",\n sync_account_posts_body={\n \"url\": \"https://www.threads.com/@yourbrand/post/DbNQAb8ABC1\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/accounts/acc_YOUR_THREADS_ACCOUNT_ID/sync\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"url\": \"https://www.threads.com/@yourbrand/post/DbNQAb8ABC1\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." }, "SyncAccountPostsBody": { "type": "object", "properties": { "url": { "type": "string", "format": "uri", "description": "Link to one post on the platform.", "examples": [ "https://www.threads.com/@you/post/DbNQAb8ABC1" ] }, "platformPostId": { "type": "string", "minLength": 1, "description": "The platform's id for one post." } } } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefusedReplayable": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFoundReplayable": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Update Post (/docs/api-reference/posts/update-post) Edits a scheduled post. Only the fields you send change, and the result is checked like a new post. Editing a post that shares its group with posts on other accounts gives it a groupId of its own. `PATCH https://api.onepostly.com/v1/posts/{id}` ```json { "paths": { "/v1/posts/{id}": { "patch": { "operationId": "updatePost", "tags": [ "Posts" ], "summary": "Update post", "description": "Edits a scheduled post. Only the fields you send change, and the result is checked like a new post. Editing a post that shares its group with posts on other accounts gives it a groupId of its own.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/PostId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdatePostBody" } } } }, "responses": { "200": { "description": "Updated post", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Post" }, "example": { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID", "platform": "instagram", "source": "onepostly", "status": "scheduled", "text": "Join our product webinar next week.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": "2027-03-16T09:00:00", "timezone": "America/New_York", "options": { "instagram": { "firstComment": "Register at the link in our profile." } }, "platformPostId": null, "url": null, "error": null, "publishedAt": null, "metrics": null, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "description": "The edit changes the text or thread of an X post and the wallet cannot cover the edited post (INSUFFICIENT_WALLET). Nothing is changed. The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No post with this id (NOT_FOUND), the post's account is no longer connected (ACCOUNT_NOT_FOUND), or a media id names no uploaded file (MEDIA_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Only a scheduled post made through Onepostly can be edited (NOT_EDITABLE). The account may also need to be reconnected (CONNECTION_INACTIVE), or quotePostId or replyToPostId names a post that is not live on its platform (POST_NOT_PUBLISHED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, PostsApi } from \"@onepostly/sdk\";\n\nconst postsApi = new PostsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await postsApi.updatePost({\n id: \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n updatePostBody: {\n \"scheduledFor\": \"2027-03-16T09:00:00\",\n \"options\": {\n \"instagram\": {\n \"firstComment\": \"Register at the link in our profile.\"\n }\n }\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.posts_api import PostsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n posts_api = PostsApi(api_client)\n response = await posts_api.update_post(\n \"pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\",\n update_post_body={\n \"scheduledFor\": \"2027-03-16T09:00:00\",\n \"options\": {\n \"instagram\": {\n \"firstComment\": \"Register at the link in our profile.\"\n }\n }\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PATCH \"https://api.onepostly.com/v1/posts/pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"scheduledFor\": \"2027-03-16T09:00:00\",\n \"options\": {\n \"instagram\": {\n \"firstComment\": \"Register at the link in our profile.\"\n }\n }\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." }, "UpdatePostBody": { "type": "object", "properties": { "text": { "type": "string", "maxLength": 63206, "description": "Replaces the post text. The account's platform limit applies. A longer text returns VALIDATION_ERROR." }, "mediaKind": { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ], "description": "What the media is. Omit it to keep the current kind, or to have it worked out again from new media." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaRef" }, "maxItems": 35, "description": "Replaces the media files, in order." }, "thread": { "type": "array", "items": { "$ref": "#/components/schemas/ThreadItemInput" }, "maxItems": 25, "description": "Replaces the thread. Send an empty list to remove it." }, "scheduledFor": { "type": "string", "minLength": 1, "maxLength": 32, "description": "New local date and time to publish, such as 2027-03-15T09:00:00, without Z or an offset. It must be at least a minute ahead. Omit it to keep the current schedule." }, "timezone": { "type": "string", "minLength": 1, "maxLength": 64, "description": "IANA timezone of scheduledFor, such as America/New_York. Omit it to keep the post's timezone." }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptionsUpdate" }, "instagram": { "$ref": "#/components/schemas/InstagramOptionsUpdate" }, "facebook": { "$ref": "#/components/schemas/FacebookOptionsUpdate" }, "threads": { "$ref": "#/components/schemas/ThreadsOptionsUpdate" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptionsUpdate" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptionsUpdate" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptionsUpdate" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptionsUpdate" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptionsUpdate" } }, "additionalProperties": false, "description": "Options under the post's platform key, as in Create Post, such as tiktok for a TikTok post. Only the options you send change. Send null to remove one. A key of another platform returns VALIDATION_ERROR.", "examples": [ { "tiktok": { "allowComment": false } } ] } }, "additionalProperties": false }, "BlueskyOptionsUpdate": { "type": "object", "properties": { "quotePostId": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": [ "string", "null" ], "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": [ "array", "null" ], "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky posts. null removes an option." }, "PinterestOptionsUpdate": { "type": "object", "properties": { "link": { "type": [ "string", "null" ], "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": [ "string", "null" ], "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": [ "boolean", "null" ], "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": [ "string", "null" ], "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest posts. null removes an option." }, "TikTokOptionsUpdate": { "type": "object", "properties": { "description": { "type": [ "string", "null" ], "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": [ "boolean", "null" ], "description": "Discloses AI-generated content." }, "privacyLevel": { "type": [ "string", "null" ], "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only", null ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": [ "boolean", "null" ], "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": [ "boolean", "null" ], "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": [ "boolean", "null" ], "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": [ "boolean", "null" ], "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": [ "boolean", "null" ], "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": [ "integer", "null" ], "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": [ "integer", "null" ], "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": [ "boolean", "null" ], "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok posts. null removes an option." }, "YouTubeOptionsUpdate": { "type": "object", "properties": { "title": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": [ "string", "null" ], "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": [ "string", "null" ], "enum": [ "public", "private", "unlisted", null ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": [ "array", "null" ], "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": [ "boolean", "null" ], "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": [ "boolean", "null" ], "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube posts. null removes an option." }, "LinkedInOptionsUpdate": { "type": "object", "properties": { "firstComment": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn posts. null removes an option." }, "ThreadsOptionsUpdate": { "type": "object", "properties": { "quotePostId": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads posts. null removes an option." }, "FacebookOptionsUpdate": { "type": "object", "properties": { "link": { "type": [ "string", "null" ], "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": [ "array", "null" ], "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": [ "array", "null" ], "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": [ "string", "null" ], "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook posts. null removes an option." }, "InstagramOptionsUpdate": { "type": "object", "properties": { "firstComment": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": [ "boolean", "null" ], "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": [ "array", "null" ], "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": [ "array", "null" ], "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": [ "integer", "null" ], "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": [ "string", "null" ], "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": [ "boolean", "null" ], "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": [ "boolean", "null" ], "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": [ "string", "null" ], "enum": [ "manual", "ss_performance", null ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": [ "integer", "null" ], "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": [ "integer", "null" ], "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": [ "boolean", "null" ], "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": [ "array", "null" ], "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": [ "boolean", "null" ], "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram posts. null removes an option." }, "XOptionsUpdate": { "type": "object", "properties": { "quotePostId": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": [ "array", "null" ], "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X posts. null removes an option." }, "ThreadItemInput": { "type": "object", "properties": { "text": { "type": "string", "maxLength": 63206, "default": "", "description": "Text of the reply. Each account's platform limit applies.", "examples": [ "Second post of the thread" ] }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaRef" }, "maxItems": 20, "default": [], "description": "Media files of the reply, in order." } }, "additionalProperties": false }, "MediaRef": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "med_7f3a9c2e1b4d4e8f9a6b5c4d3e2f1a0b" ], "description": "A media asset uploaded with Create Media." }, "url": { "type": "string", "maxLength": 2048, "format": "uri", "description": "A public HTTPS URL of the file.", "examples": [ "https://cdn.onepostly.com/media/product.jpg" ] } }, "additionalProperties": false, "description": "A media file: send id or url." } }, "parameters": { "PostId": { "schema": { "type": "string", "minLength": 1, "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Create Profile (/docs/api-reference/profiles/create-profile) `POST https://api.onepostly.com/v1/profiles` ```json { "paths": { "/v1/profiles": { "post": { "operationId": "createProfile", "tags": [ "Profiles" ], "summary": "Create profile", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateProfileBody" } } } }, "responses": { "201": { "description": "Created profile", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Profile" }, "example": { "name": "Business", "accountCount": 0, "createdAt": "2027-03-15T09:00:00.000Z", "updatedAt": "2027-03-15T09:00:00.000Z" } } } }, "400": { "$ref": "#/components/responses/BadRequestReplayable" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "409": { "description": "The workspace already has a profile with this name in any letter case, or the name is none, which is reserved (PROFILE_NAME_TAKEN). The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, ProfilesApi } from \"@onepostly/sdk\";\n\nconst profilesApi = new ProfilesApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await profilesApi.createProfile({\n createProfileBody: {\n \"name\": \"Business\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.profiles_api import ProfilesApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n profiles_api = ProfilesApi(api_client)\n response = await profiles_api.create_profile(\n create_profile_body={\n \"name\": \"Business\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/profiles\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"name\": \"Business\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Profile": { "type": "object", "properties": { "name": { "type": "string", "description": "The profile's name. It identifies the profile and is unique in the workspace, ignoring letter case.", "examples": [ "Business" ] }, "accountCount": { "type": "integer", "description": "Connected accounts filed under this profile.", "examples": [ 4 ] }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "updatedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "name", "accountCount", "createdAt", "updatedAt" ] }, "CreateProfileBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 60, "description": "Profile name. It must be unique in the workspace, ignoring letter case. none is reserved.", "examples": [ "Business" ] } }, "required": [ "name" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequestReplayable": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Delete Profile (/docs/api-reference/profiles/delete-profile) Deletes a profile. Its accounts stay connected and are no longer filed under a profile. `DELETE https://api.onepostly.com/v1/profiles/{name}` ```json { "paths": { "/v1/profiles/{name}": { "delete": { "operationId": "deleteProfile", "tags": [ "Profiles" ], "summary": "Delete profile", "description": "Deletes a profile. Its accounts stay connected and are no longer filed under a profile.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/ProfileName" } ], "responses": { "204": { "description": "Deleted", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No profile with this name (PROFILE_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "An API key is limited to this profile (PROFILE_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, ProfilesApi } from \"@onepostly/sdk\";\n\nconst profilesApi = new ProfilesApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await profilesApi.deleteProfile({\n name: \"Business\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.profiles_api import ProfilesApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n profiles_api = ProfilesApi(api_client)\n response = await profiles_api.delete_profile(\n \"Business\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/profiles/Business\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] } }, "parameters": { "ProfileName": { "schema": { "type": "string", "minLength": 1, "maxLength": 60, "description": "The profile's name, URL-encoded. Letter case does not matter. For example, Client Team is sent as Client%20Team.", "examples": [ "Business" ] }, "required": true, "description": "The profile's name, URL-encoded. Letter case does not matter. For example, Client Team is sent as Client%20Team.", "name": "name", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Profiles (/docs/api-reference/profiles/list-profiles) Lists the workspace's profiles, oldest first. Profiles group connected accounts. A key limited to one profile lists only that profile. `GET https://api.onepostly.com/v1/profiles` ```json { "paths": { "/v1/profiles": { "get": { "operationId": "listProfiles", "tags": [ "Profiles" ], "summary": "List profiles", "description": "Lists the workspace's profiles, oldest first. Profiles group connected accounts. A key limited to one profile lists only that profile.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/Limit50Max100" }, { "$ref": "#/components/parameters/Cursor" } ], "responses": { "200": { "description": "Profiles", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Profile" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "name": "Default", "accountCount": 2, "createdAt": "2027-03-01T09:00:00.000Z", "updatedAt": "2027-03-01T09:00:00.000Z" }, { "name": "Business", "accountCount": 3, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-01T10:00:00.000Z" } ], "nextCursor": null, "hasMore": false } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, ProfilesApi } from \"@onepostly/sdk\";\n\nconst profilesApi = new ProfilesApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await profilesApi.listProfiles();\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.profiles_api import ProfilesApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n profiles_api = ProfilesApi(api_client)\n response = await profiles_api.list_profiles()\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/profiles\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Profile": { "type": "object", "properties": { "name": { "type": "string", "description": "The profile's name. It identifies the profile and is unique in the workspace, ignoring letter case.", "examples": [ "Business" ] }, "accountCount": { "type": "integer", "description": "Connected accounts filed under this profile.", "examples": [ 4 ] }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "updatedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "name", "accountCount", "createdAt", "updatedAt" ] } }, "parameters": { "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max100": { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50, "description": "Items per page. Defaults to 50. Maximum 100.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 100.", "name": "limit", "in": "query" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Rename Profile (/docs/api-reference/profiles/update-profile) Renames a profile. Its accounts stay filed under it. Filters that name the profile must use the new name from then on. `PATCH https://api.onepostly.com/v1/profiles/{name}` ```json { "paths": { "/v1/profiles/{name}": { "patch": { "operationId": "updateProfile", "tags": [ "Profiles" ], "summary": "Rename profile", "description": "Renames a profile. Its accounts stay filed under it. Filters that name the profile must use the new name from then on.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/ProfileName" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateProfileBody" } } } }, "responses": { "200": { "description": "Updated profile", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Profile" }, "example": { "name": "Acme Business", "accountCount": 3, "createdAt": "2027-03-01T10:00:00.000Z", "updatedAt": "2027-03-15T10:00:00.000Z" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No profile with this name (PROFILE_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The workspace already has a profile with this name in any letter case, or the name is none, which is reserved (PROFILE_NAME_TAKEN)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, ProfilesApi } from \"@onepostly/sdk\";\n\nconst profilesApi = new ProfilesApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await profilesApi.updateProfile({\n name: \"Business\",\n updateProfileBody: {\n \"name\": \"Acme Business\"\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.profiles_api import ProfilesApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n profiles_api = ProfilesApi(api_client)\n response = await profiles_api.update_profile(\n \"Business\",\n update_profile_body={\n \"name\": \"Acme Business\"\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PATCH \"https://api.onepostly.com/v1/profiles/Business\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"name\": \"Acme Business\"\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Profile": { "type": "object", "properties": { "name": { "type": "string", "description": "The profile's name. It identifies the profile and is unique in the workspace, ignoring letter case.", "examples": [ "Business" ] }, "accountCount": { "type": "integer", "description": "Connected accounts filed under this profile.", "examples": [ 4 ] }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "updatedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "name", "accountCount", "createdAt", "updatedAt" ] }, "UpdateProfileBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 60, "description": "Profile name. It must be unique in the workspace, ignoring letter case. none is reserved.", "examples": [ "Business" ] } }, "required": [ "name" ] } }, "parameters": { "ProfileName": { "schema": { "type": "string", "minLength": 1, "maxLength": 60, "description": "The profile's name, URL-encoded. Letter case does not matter. For example, Client Team is sent as Client%20Team.", "examples": [ "Business" ] }, "required": true, "description": "The profile's name, URL-encoded. Letter case does not matter. For example, Client Team is sent as Client%20Team.", "name": "name", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get TikTok Creator Info (/docs/api-reference/tiktok/get-creator-info) Returns the privacy options and publishing limits of a TikTok account. TikTok asks apps to read them before every post. `GET https://api.onepostly.com/v1/accounts/{id}/creator-info` ```json { "paths": { "/v1/accounts/{id}/creator-info": { "get": { "operationId": "getCreatorInfo", "tags": [ "Accounts" ], "summary": "Get TikTok creator info", "description": "Returns the privacy options and publishing limits of a TikTok account. TikTok asks apps to read them before every post.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/AccountId" } ], "responses": { "200": { "description": "Creator info", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreatorInfo" }, "example": { "accountId": "acc_YOUR_TIKTOK_ACCOUNT_ID", "username": "yourbrand", "nickname": "Your Brand", "avatarUrl": "https://p16-sign-va.tiktokcdn.com/tos-maliva-avt-0068/7310942817465028614~c5_168x168.jpeg", "privacyLevelOptions": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "commentDisabled": false, "duetDisabled": false, "stitchDisabled": false, "maxVideoPostDurationSec": 600, "fetchedAt": "2027-03-15T08:59:30.000Z" } } } }, "400": { "description": "The request is invalid (VALIDATION_ERROR), or the account is not a TikTok account (UNSUPPORTED_PLATFORM)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/PlatformRefused" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" }, "502": { "$ref": "#/components/responses/PlatformFailed" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, AccountsApi } from \"@onepostly/sdk\";\n\nconst accountsApi = new AccountsApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await accountsApi.getCreatorInfo({\n id: \"acc_YOUR_TIKTOK_ACCOUNT_ID\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.accounts_api import AccountsApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n accounts_api = AccountsApi(api_client)\n response = await accounts_api.get_creator_info(\n \"acc_YOUR_TIKTOK_ACCOUNT_ID\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/accounts/acc_YOUR_TIKTOK_ACCOUNT_ID/creator-info\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "CreatorInfo": { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "username": { "type": [ "string", "null" ], "examples": [ "onepostly" ] }, "nickname": { "type": [ "string", "null" ], "examples": [ "Onepostly" ] }, "avatarUrl": { "type": [ "string", "null" ], "examples": [ "https://cdn.onepostly.com/avatars/onepostly.jpg" ] }, "privacyLevelOptions": { "type": "array", "items": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ] }, "description": "The privacyLevel values this creator may publish with.", "examples": [ [ "public_to_everyone", "self_only" ] ] }, "commentDisabled": { "type": "boolean", "description": "true when the creator turned comments off in TikTok.", "examples": [ false ] }, "duetDisabled": { "type": "boolean", "description": "true when the creator turned duets off in TikTok.", "examples": [ false ] }, "stitchDisabled": { "type": "boolean", "description": "true when the creator turned stitches off in TikTok.", "examples": [ false ] }, "maxVideoPostDurationSec": { "type": [ "number", "null" ], "description": "Longest video this creator may post, in seconds. Null when TikTok does not report it.", "examples": [ 600 ] }, "fetchedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "accountId", "username", "nickname", "avatarUrl", "privacyLevelOptions", "commentDisabled", "duetDisabled", "stitchDisabled", "maxVideoPostDurationSec", "fetchedAt" ] } }, "parameters": { "AccountId": { "schema": { "type": "string", "minLength": 1, "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "PlatformFailed": { "description": "The platform failed, is not accepting requests right now, or did not respond. The failure is temporary, so try again later", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PlatformRefused": { "description": "The platform refused the request. Sending it again unchanged fails the same way", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Conflict": { "description": "The account must be reconnected (TOKEN_EXPIRED, TOKEN_INVALID)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "No account with this id is connected to the workspace (ACCOUNT_NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Wallet Balance (/docs/api-reference/wallet/get-wallet-balance) Returns the workspace's prepaid wallet balance. X actions are paid from it. When it is too low, they return INSUFFICIENT_WALLET. `GET https://api.onepostly.com/v1/wallet` ```json { "paths": { "/v1/wallet": { "get": { "operationId": "getWalletBalance", "tags": [ "Wallet" ], "summary": "Get wallet balance", "description": "Returns the workspace's prepaid wallet balance. X actions are paid from it. When it is too low, they return INSUFFICIENT_WALLET.", "security": [ { "Bearer": [] } ], "responses": { "200": { "description": "Wallet", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Wallet" }, "example": { "balance": "12.345", "currency": "usd" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WalletApi } from \"@onepostly/sdk\";\n\nconst walletApi = new WalletApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await walletApi.getWalletBalance();\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.wallet_api import WalletApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n wallet_api = WalletApi(api_client)\n response = await wallet_api.get_wallet_balance()\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/wallet\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Wallet": { "type": "object", "properties": { "balance": { "type": "string", "description": "The balance in US dollars, with three decimal places.", "examples": [ "12.345" ] }, "currency": { "type": "string", "enum": [ "usd" ], "description": "Always usd.", "examples": [ "usd" ] } }, "required": [ "balance", "currency" ] } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Account Connected (/docs/api-reference/webhook-events/account-connected) Sent when an account is connected, or an existing account is reconnected. The object is the account, as Get Account returns it, with reconnected telling the two apart. Webhook event `account.connected`, sent as a `POST` to your endpoint ```json { "webhooks": { "account.connected": { "post": { "tags": [ "Webhooks" ], "summary": "Account connected", "description": "Sent when an account is connected, or an existing account is reconnected. The object is the account, as Get Account returns it, with reconnected telling the two apart.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "account.connected" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountConnectedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "AccountConnectedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "account.connected" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/ConnectedAccount" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "ConnectedAccount": { "allOf": [ { "$ref": "#/components/schemas/Account" }, { "type": "object", "properties": { "reconnected": { "type": "boolean", "description": "true when an account already connected to this workspace was authorized again, such as after it expired. false for a new connection, and for an account connected again after it was disconnected.", "examples": [ false ] } }, "required": [ "reconnected" ] } ] }, "Account": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "displayName": { "type": "string", "examples": [ "Onepostly" ] }, "handle": { "type": "string", "description": "The account's handle on the platform, without a leading @. LinkedIn has no handles, so a LinkedIn account has its name here.", "examples": [ "onepostly" ] }, "avatarUrl": { "type": [ "string", "null" ], "format": "uri", "examples": [ "https://cdn.onepostly.com/avatars/onepostly.jpg" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "active", "expired", "revoked", "error" ] }, { "type": "string" } ], "description": "active works normally. expired, revoked and error need a reconnect before the account can publish again. expired also covers an authorization that ran out and cannot renew by itself. A disconnected account is no longer returned. The account.disconnected webhook sends it as a DisconnectedAccount. New values can be added, so handle a value you do not know.", "examples": [ "active" ] }, "canAutoRenew": { "type": "boolean", "description": "Whether the authorization renews without the account owner signing in again.", "examples": [ true ] }, "tokenExpiresAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the current authorization expires, or null when it does not.", "examples": [ "2026-12-25T10:00:00.000Z" ] }, "profile": { "type": [ "string", "null" ], "description": "The name of the profile the account is filed under. null when the account is in no profile.", "examples": [ "Business" ] }, "metadata": { "$ref": "#/components/schemas/AccountMetadata", "description": "The metadata sent with the connect that added the account. An empty object when none was sent." }, "xSubscriptionType": { "type": [ "string", "null" ], "description": "X only, such as Premium. The account's X subscription, which sets its post length limit. Null when X does not report it, and left out for other platforms." }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "updatedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "platform", "displayName", "handle", "avatarUrl", "status", "canAutoRenew", "tokenExpiresAt", "profile", "metadata", "createdAt", "updatedAt" ] }, "AccountMetadata": { "type": "object", "additionalProperties": { "type": "string", "maxLength": 500 }, "description": "Your own key-value pairs for the account, such as the id of the user in your app who connected it. Up to 20 keys. Keys are 1 to 40 characters and values up to 500. Do not store secrets here.", "examples": [ { "userId": "user_8412" } ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Account Disconnected (/docs/api-reference/webhook-events/account-disconnected) Sent when an account is disconnected, by you or by its owner on the platform. The API no longer returns the account, so keep its handle from this event if you need it. Webhook event `account.disconnected`, sent as a `POST` to your endpoint ```json { "webhooks": { "account.disconnected": { "post": { "tags": [ "Webhooks" ], "summary": "Account disconnected", "description": "Sent when an account is disconnected, by you or by its owner on the platform. The API no longer returns the account, so keep its handle from this event if you need it.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "account.disconnected" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountDisconnectedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "AccountDisconnectedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "account.disconnected" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/DisconnectedAccount" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "DisconnectedAccount": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "handle": { "type": "string", "description": "The account's handle when it was disconnected, without a leading @, as in Account. An empty string if it had none.", "examples": [ "onepostly" ] }, "status": { "type": "string", "enum": [ "disconnected" ], "description": "Always disconnected. The account is no longer returned by List Accounts or Get Account." }, "metadata": { "$ref": "#/components/schemas/AccountMetadata", "description": "The account's metadata when it was disconnected. The account no longer keeps it." } }, "required": [ "id", "platform", "handle", "status", "metadata" ] }, "AccountMetadata": { "type": "object", "additionalProperties": { "type": "string", "maxLength": 500 }, "description": "Your own key-value pairs for the account, such as the id of the user in your app who connected it. Up to 20 keys. Keys are 1 to 40 characters and values up to 500. Do not store secrets here.", "examples": [ { "userId": "user_8412" } ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Account Expired (/docs/api-reference/webhook-events/account-expired) Sent when the account's authorization expired. Reconnect the account to publish to it again. Webhook event `account.expired`, sent as a `POST` to your endpoint ```json { "webhooks": { "account.expired": { "post": { "tags": [ "Webhooks" ], "summary": "Account expired", "description": "Sent when the account's authorization expired. Reconnect the account to publish to it again.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "account.expired" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountExpiredEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "AccountExpiredEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "account.expired" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/AccountAuthFailure" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "AccountAuthFailure": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "handle": { "type": [ "string", "null" ], "description": "The account's handle, without a leading @, as in Account. Null if it has none.", "examples": [ "onepostly" ] }, "status": { "type": "string", "enum": [ "expired", "revoked" ], "description": "The account's new status, matching the event name.", "examples": [ "expired" ] }, "reason": { "anyOf": [ { "type": "string", "enum": [ "expired", "refresh_failed", "token_invalid", "refresh_revoked" ] }, { "type": "string" } ], "description": "Why the account stopped working. expired and refresh_failed come with account.expired, token_invalid and refresh_revoked with account.revoked. Reconnect the account in every case. New values can be added, so handle a value you do not know.", "examples": [ "expired" ] }, "tokenExpiresAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the account's last authorization expires, or null when the platform sets no expiry.", "examples": [ "2027-05-14T09:00:00.000Z" ] }, "previousStatus": { "anyOf": [ { "type": "string", "enum": [ "active", "error", "expired" ] }, { "type": "string" } ], "description": "The account's status just before this change. expired only appears on account.revoked. New values can be added, so handle a value you do not know.", "examples": [ "active" ] } }, "required": [ "id", "platform", "handle", "status", "reason", "tokenExpiresAt", "previousStatus" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Account Expiring (/docs/api-reference/webhook-events/account-expiring) Sent about 7 days before tokenExpiresAt for an account that cannot renew its authorization by itself. Reconnect it before then. Webhook event `account.expiring`, sent as a `POST` to your endpoint ```json { "webhooks": { "account.expiring": { "post": { "tags": [ "Webhooks" ], "summary": "Account expiring", "description": "Sent about 7 days before tokenExpiresAt for an account that cannot renew its authorization by itself. Reconnect it before then.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "account.expiring" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountExpiringEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "AccountExpiringEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "account.expiring" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/Account" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "Account": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "displayName": { "type": "string", "examples": [ "Onepostly" ] }, "handle": { "type": "string", "description": "The account's handle on the platform, without a leading @. LinkedIn has no handles, so a LinkedIn account has its name here.", "examples": [ "onepostly" ] }, "avatarUrl": { "type": [ "string", "null" ], "format": "uri", "examples": [ "https://cdn.onepostly.com/avatars/onepostly.jpg" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "active", "expired", "revoked", "error" ] }, { "type": "string" } ], "description": "active works normally. expired, revoked and error need a reconnect before the account can publish again. expired also covers an authorization that ran out and cannot renew by itself. A disconnected account is no longer returned. The account.disconnected webhook sends it as a DisconnectedAccount. New values can be added, so handle a value you do not know.", "examples": [ "active" ] }, "canAutoRenew": { "type": "boolean", "description": "Whether the authorization renews without the account owner signing in again.", "examples": [ true ] }, "tokenExpiresAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the current authorization expires, or null when it does not.", "examples": [ "2026-12-25T10:00:00.000Z" ] }, "profile": { "type": [ "string", "null" ], "description": "The name of the profile the account is filed under. null when the account is in no profile.", "examples": [ "Business" ] }, "metadata": { "$ref": "#/components/schemas/AccountMetadata", "description": "The metadata sent with the connect that added the account. An empty object when none was sent." }, "xSubscriptionType": { "type": [ "string", "null" ], "description": "X only, such as Premium. The account's X subscription, which sets its post length limit. Null when X does not report it, and left out for other platforms." }, "createdAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] }, "updatedAt": { "type": "string", "format": "date-time", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "platform", "displayName", "handle", "avatarUrl", "status", "canAutoRenew", "tokenExpiresAt", "profile", "metadata", "createdAt", "updatedAt" ] }, "AccountMetadata": { "type": "object", "additionalProperties": { "type": "string", "maxLength": 500 }, "description": "Your own key-value pairs for the account, such as the id of the user in your app who connected it. Up to 20 keys. Keys are 1 to 40 characters and values up to 500. Do not store secrets here.", "examples": [ { "userId": "user_8412" } ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Account Revoked (/docs/api-reference/webhook-events/account-revoked) Sent when the platform rejected the account's authorization, or its owner withdrew it. Reconnect the account to publish to it again. Webhook event `account.revoked`, sent as a `POST` to your endpoint ```json { "webhooks": { "account.revoked": { "post": { "tags": [ "Webhooks" ], "summary": "Account revoked", "description": "Sent when the platform rejected the account's authorization, or its owner withdrew it. Reconnect the account to publish to it again.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "account.revoked" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountRevokedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "AccountRevokedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "account.revoked" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/AccountAuthFailure" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "AccountAuthFailure": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "handle": { "type": [ "string", "null" ], "description": "The account's handle, without a leading @, as in Account. Null if it has none.", "examples": [ "onepostly" ] }, "status": { "type": "string", "enum": [ "expired", "revoked" ], "description": "The account's new status, matching the event name.", "examples": [ "expired" ] }, "reason": { "anyOf": [ { "type": "string", "enum": [ "expired", "refresh_failed", "token_invalid", "refresh_revoked" ] }, { "type": "string" } ], "description": "Why the account stopped working. expired and refresh_failed come with account.expired, token_invalid and refresh_revoked with account.revoked. Reconnect the account in every case. New values can be added, so handle a value you do not know.", "examples": [ "expired" ] }, "tokenExpiresAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the account's last authorization expires, or null when the platform sets no expiry.", "examples": [ "2027-05-14T09:00:00.000Z" ] }, "previousStatus": { "anyOf": [ { "type": "string", "enum": [ "active", "error", "expired" ] }, { "type": "string" } ], "description": "The account's status just before this change. expired only appears on account.revoked. New values can be added, so handle a value you do not know.", "examples": [ "active" ] } }, "required": [ "id", "platform", "handle", "status", "reason", "tokenExpiresAt", "previousStatus" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Comment Created (/docs/api-reference/webhook-events/comment-created) Sent when you comment with POST /v1/posts/{id}/comments or reply with POST /v1/comments/{id}/replies. Webhook event `comment.created`, sent as a `POST` to your endpoint ```json { "webhooks": { "comment.created": { "post": { "tags": [ "Webhooks" ], "summary": "Comment created", "description": "Sent when you comment with POST /v1/posts/{id}/comments or reply with POST /v1/comments/{id}/replies.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "comment.created" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentCreatedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "CommentCreatedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "comment.created" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/Comment" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "Comment": { "type": "object", "properties": { "id": { "type": "string", "description": "The comment's id. Use it to reply to, hide, like or delete the comment.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post the comment is on." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that published the post." }, "platform": { "$ref": "#/components/schemas/Platform" }, "platformCommentId": { "type": "string", "description": "The platform's own id for the comment.", "examples": [ "17895695668004550" ] }, "parentId": { "type": [ "string", "null" ], "description": "The comment this one replies to, or null for a comment on the post." }, "text": { "type": "string", "examples": [ "Love this!" ] }, "username": { "type": [ "string", "null" ], "description": "The author's username, without a leading @. Null when the platform does not share it.", "examples": [ "jane_doe" ] }, "likeCount": { "type": [ "integer", "null" ], "description": "Likes on the comment. Null when the platform does not report it.", "examples": [ 12 ] }, "createdAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the comment was posted. Null when the platform does not report it.", "examples": [ "2026-08-25T10:05:00.000Z" ] }, "replies": { "type": "array", "items": { "$ref": "#/components/schemas/Comment" }, "description": "Replies, on platforms that return them with the comment." } }, "required": [ "id", "postId", "accountId", "platform", "platformCommentId", "parentId", "text", "username", "likeCount", "createdAt", "replies" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Comment Deleted (/docs/api-reference/webhook-events/comment-deleted) Sent when you delete a comment with DELETE /v1/comments/{id}, or when a comment on a post Onepostly knows is removed on Facebook. Webhook event `comment.deleted`, sent as a `POST` to your endpoint ```json { "webhooks": { "comment.deleted": { "post": { "tags": [ "Webhooks" ], "summary": "Comment deleted", "description": "Sent when you delete a comment with DELETE /v1/comments/{id}, or when a comment on a post Onepostly knows is removed on Facebook.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "comment.deleted" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentDeletedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "CommentDeletedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "comment.deleted" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/DeletedComment" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "DeletedComment": { "type": "object", "properties": { "id": { "type": "string", "description": "The deleted comment's id.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post the comment was on." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that published the post." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "platformCommentId": { "type": "string", "description": "The platform's own id for the comment.", "examples": [ "17895695668004550" ] } }, "required": [ "id", "postId", "accountId", "platform", "platformCommentId" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Comment Received (/docs/api-reference/webhook-events/comment-received) Sent when anyone comments or replies on a post of a connected Facebook Page or Instagram account. Reply with the event's comment id. Webhook event `comment.received`, sent as a `POST` to your endpoint ```json { "webhooks": { "comment.received": { "post": { "tags": [ "Webhooks" ], "summary": "Comment received", "description": "Sent when anyone comments or replies on a post of a connected Facebook Page or Instagram account. Reply with the event's comment id.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "comment.received" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentReceivedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "CommentReceivedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "comment.received" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/ReceivedComment" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "ReceivedComment": { "allOf": [ { "$ref": "#/components/schemas/Comment" }, { "type": "object", "properties": { "authorId": { "type": [ "string", "null" ], "description": "The commenter's platform user id, or null when the platform does not share it.", "examples": [ "7012345678901234" ] } }, "required": [ "authorId" ] } ] }, "Comment": { "type": "object", "properties": { "id": { "type": "string", "description": "The comment's id. Use it to reply to, hide, like or delete the comment.", "examples": [ "cmt_38D25EzbeGBZyvkVv6arWxGCQ4XbjQPw8o9EV1RrKmfsbN207QSUt2LI8ZeiZu0HaA7hEg0ddFNWKHNowMaq5PgczxaypKvlMHOiEplNWEHdZU847FWjVqN" ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post the comment is on." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that published the post." }, "platform": { "$ref": "#/components/schemas/Platform" }, "platformCommentId": { "type": "string", "description": "The platform's own id for the comment.", "examples": [ "17895695668004550" ] }, "parentId": { "type": [ "string", "null" ], "description": "The comment this one replies to, or null for a comment on the post." }, "text": { "type": "string", "examples": [ "Love this!" ] }, "username": { "type": [ "string", "null" ], "description": "The author's username, without a leading @. Null when the platform does not share it.", "examples": [ "jane_doe" ] }, "likeCount": { "type": [ "integer", "null" ], "description": "Likes on the comment. Null when the platform does not report it.", "examples": [ 12 ] }, "createdAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the comment was posted. Null when the platform does not report it.", "examples": [ "2026-08-25T10:05:00.000Z" ] }, "replies": { "type": "array", "items": { "$ref": "#/components/schemas/Comment" }, "description": "Replies, on platforms that return them with the comment." } }, "required": [ "id", "postId", "accountId", "platform", "platformCommentId", "parentId", "text", "username", "likeCount", "createdAt", "replies" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Bookmarked (/docs/api-reference/webhook-events/engagement-bookmarked) Sent when PUT /v1/accounts/{id}/bookmarks/{postId} succeeds. Webhook event `engagement.bookmarked`, sent as a `POST` to your endpoint ```json { "webhooks": { "engagement.bookmarked": { "post": { "tags": [ "Webhooks" ], "summary": "Post bookmarked", "description": "Sent when PUT /v1/accounts/{id}/bookmarks/{postId} succeeds.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "engagement.bookmarked" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EngagementBookmarkedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "EngagementBookmarkedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "engagement.bookmarked" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/EngagementAction" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "EngagementAction": { "type": "object", "properties": { "action": { "type": "string", "enum": [ "like", "bookmark", "repost" ], "description": "What the account did.", "examples": [ "like" ] }, "active": { "type": "boolean", "description": "true after a like, bookmark or repost, false after it is removed.", "examples": [ true ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post acted on. Pass it in the path to undo the action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that did the action." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "platformPostId": { "type": "string", "description": "The post's id on the platform.", "examples": [ "1900876543210987654" ] }, "platformRepostId": { "type": [ "string", "null" ], "description": "engagement.reposted only. The repost's own id on the platform, or null when the platform does not return one.", "examples": [ "1900876543210987999" ] } }, "required": [ "action", "active", "postId", "accountId", "platform", "platformPostId" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Liked (/docs/api-reference/webhook-events/engagement-liked) Sent when PUT /v1/accounts/{id}/likes/{postId} succeeds. Webhook event `engagement.liked`, sent as a `POST` to your endpoint ```json { "webhooks": { "engagement.liked": { "post": { "tags": [ "Webhooks" ], "summary": "Post liked", "description": "Sent when PUT /v1/accounts/{id}/likes/{postId} succeeds.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "engagement.liked" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EngagementLikedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "EngagementLikedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "engagement.liked" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/EngagementAction" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "EngagementAction": { "type": "object", "properties": { "action": { "type": "string", "enum": [ "like", "bookmark", "repost" ], "description": "What the account did.", "examples": [ "like" ] }, "active": { "type": "boolean", "description": "true after a like, bookmark or repost, false after it is removed.", "examples": [ true ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post acted on. Pass it in the path to undo the action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that did the action." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "platformPostId": { "type": "string", "description": "The post's id on the platform.", "examples": [ "1900876543210987654" ] }, "platformRepostId": { "type": [ "string", "null" ], "description": "engagement.reposted only. The repost's own id on the platform, or null when the platform does not return one.", "examples": [ "1900876543210987999" ] } }, "required": [ "action", "active", "postId", "accountId", "platform", "platformPostId" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Reposted (/docs/api-reference/webhook-events/engagement-reposted) Sent when PUT /v1/accounts/{id}/reposts/{postId} succeeds. Webhook event `engagement.reposted`, sent as a `POST` to your endpoint ```json { "webhooks": { "engagement.reposted": { "post": { "tags": [ "Webhooks" ], "summary": "Post reposted", "description": "Sent when PUT /v1/accounts/{id}/reposts/{postId} succeeds.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "engagement.reposted" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EngagementRepostedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "EngagementRepostedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "engagement.reposted" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/EngagementAction" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "EngagementAction": { "type": "object", "properties": { "action": { "type": "string", "enum": [ "like", "bookmark", "repost" ], "description": "What the account did.", "examples": [ "like" ] }, "active": { "type": "boolean", "description": "true after a like, bookmark or repost, false after it is removed.", "examples": [ true ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post acted on. Pass it in the path to undo the action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that did the action." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "platformPostId": { "type": "string", "description": "The post's id on the platform.", "examples": [ "1900876543210987654" ] }, "platformRepostId": { "type": [ "string", "null" ], "description": "engagement.reposted only. The repost's own id on the platform, or null when the platform does not return one.", "examples": [ "1900876543210987999" ] } }, "required": [ "action", "active", "postId", "accountId", "platform", "platformPostId" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Unbookmarked (/docs/api-reference/webhook-events/engagement-unbookmarked) Sent when DELETE /v1/accounts/{id}/bookmarks/{postId} succeeds. Webhook event `engagement.unbookmarked`, sent as a `POST` to your endpoint ```json { "webhooks": { "engagement.unbookmarked": { "post": { "tags": [ "Webhooks" ], "summary": "Post unbookmarked", "description": "Sent when DELETE /v1/accounts/{id}/bookmarks/{postId} succeeds.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "engagement.unbookmarked" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EngagementUnbookmarkedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "EngagementUnbookmarkedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "engagement.unbookmarked" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/EngagementAction" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "EngagementAction": { "type": "object", "properties": { "action": { "type": "string", "enum": [ "like", "bookmark", "repost" ], "description": "What the account did.", "examples": [ "like" ] }, "active": { "type": "boolean", "description": "true after a like, bookmark or repost, false after it is removed.", "examples": [ true ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post acted on. Pass it in the path to undo the action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that did the action." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "platformPostId": { "type": "string", "description": "The post's id on the platform.", "examples": [ "1900876543210987654" ] }, "platformRepostId": { "type": [ "string", "null" ], "description": "engagement.reposted only. The repost's own id on the platform, or null when the platform does not return one.", "examples": [ "1900876543210987999" ] } }, "required": [ "action", "active", "postId", "accountId", "platform", "platformPostId" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Unliked (/docs/api-reference/webhook-events/engagement-unliked) Sent when DELETE /v1/accounts/{id}/likes/{postId} succeeds. Webhook event `engagement.unliked`, sent as a `POST` to your endpoint ```json { "webhooks": { "engagement.unliked": { "post": { "tags": [ "Webhooks" ], "summary": "Post unliked", "description": "Sent when DELETE /v1/accounts/{id}/likes/{postId} succeeds.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "engagement.unliked" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EngagementUnlikedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "EngagementUnlikedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "engagement.unliked" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/EngagementAction" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "EngagementAction": { "type": "object", "properties": { "action": { "type": "string", "enum": [ "like", "bookmark", "repost" ], "description": "What the account did.", "examples": [ "like" ] }, "active": { "type": "boolean", "description": "true after a like, bookmark or repost, false after it is removed.", "examples": [ true ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post acted on. Pass it in the path to undo the action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that did the action." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "platformPostId": { "type": "string", "description": "The post's id on the platform.", "examples": [ "1900876543210987654" ] }, "platformRepostId": { "type": [ "string", "null" ], "description": "engagement.reposted only. The repost's own id on the platform, or null when the platform does not return one.", "examples": [ "1900876543210987999" ] } }, "required": [ "action", "active", "postId", "accountId", "platform", "platformPostId" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Unreposted (/docs/api-reference/webhook-events/engagement-unreposted) Sent when DELETE /v1/accounts/{id}/reposts/{postId} succeeds. Webhook event `engagement.unreposted`, sent as a `POST` to your endpoint ```json { "webhooks": { "engagement.unreposted": { "post": { "tags": [ "Webhooks" ], "summary": "Post unreposted", "description": "Sent when DELETE /v1/accounts/{id}/reposts/{postId} succeeds.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "engagement.unreposted" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EngagementUnrepostedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "EngagementUnrepostedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "engagement.unreposted" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/EngagementAction" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "EngagementAction": { "type": "object", "properties": { "action": { "type": "string", "enum": [ "like", "bookmark", "repost" ], "description": "What the account did.", "examples": [ "like" ] }, "active": { "type": "boolean", "description": "true after a like, bookmark or repost, false after it is removed.", "examples": [ true ] }, "postId": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ], "description": "The post acted on. Pass it in the path to undo the action." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The account that did the action." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "platformPostId": { "type": "string", "description": "The post's id on the platform.", "examples": [ "1900876543210987654" ] }, "platformRepostId": { "type": [ "string", "null" ], "description": "engagement.reposted only. The repost's own id on the platform, or null when the platform does not return one.", "examples": [ "1900876543210987999" ] } }, "required": [ "action", "active", "postId", "accountId", "platform", "platformPostId" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Message Deleted (/docs/api-reference/webhook-events/message-deleted) Sent when the person unsends a message. Instagram only. Webhook event `message.deleted`, sent as a `POST` to your endpoint ```json { "webhooks": { "message.deleted": { "post": { "tags": [ "Webhooks" ], "summary": "Message deleted", "description": "Sent when the person unsends a message. Instagram only.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "message.deleted" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageDeletedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "MessageDeletedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "message.deleted" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/UnsentMessage" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "UnsentMessage": { "type": "object", "properties": { "id": { "type": "string", "description": "The unsent message, the same id its message.received carried.", "examples": [ "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDUyOTA2MzE4Mjc0OjM0MDI4MjM2Njg0" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The connected Facebook Page or Instagram account." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "conversationId": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "senderId": { "type": "string", "description": "The platform's id for the sending side.", "examples": [ "6845123987456321" ] }, "recipientId": { "type": "string", "description": "The platform's id for the receiving side.", "examples": [ "17841452906318274" ] }, "sentAt": { "type": "string", "format": "date-time", "description": "When the event happened on the platform, in ISO 8601.", "examples": [ "2027-03-15T14:05:11.000Z" ] } }, "required": [ "id", "accountId", "platform", "conversationId", "senderId", "recipientId", "sentAt" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Message Delivered (/docs/api-reference/webhook-events/message-delivered) Sent when messages the account sent reach the person. Webhook event `message.delivered`, sent as a `POST` to your endpoint ```json { "webhooks": { "message.delivered": { "post": { "tags": [ "Webhooks" ], "summary": "Message delivered", "description": "Sent when messages the account sent reach the person.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "message.delivered" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageDeliveredEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "MessageDeliveredEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "message.delivered" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/MessageDeliveryReceipt" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "MessageDeliveryReceipt": { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The connected Facebook Page or Instagram account." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "conversationId": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "senderId": { "type": "string", "description": "The platform's id for the sending side.", "examples": [ "6845123987456321" ] }, "recipientId": { "type": "string", "description": "The platform's id for the receiving side.", "examples": [ "17841452906318274" ] }, "messageIds": { "type": "array", "items": { "type": "string" }, "description": "The delivered messages. It can be empty, so rely on watermark then.", "examples": [ [ "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDUyOTA2MzE4Mjc0OjM0MDI4MjM2Njg0" ] ] }, "watermark": { "type": [ "integer", "null" ], "description": "Unix time in milliseconds. Every message the account sent in this conversation before it is covered. null when the platform sends none.", "examples": [ 1805119651000 ] }, "sentAt": { "type": "string", "format": "date-time", "description": "When the event happened on the platform, in ISO 8601.", "examples": [ "2027-03-15T14:05:11.000Z" ] } }, "required": [ "accountId", "platform", "conversationId", "senderId", "recipientId", "messageIds", "watermark", "sentAt" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Message Postback (/docs/api-reference/webhook-events/message-postback) Sent when the person taps a postback button, a persistent menu item or an ice breaker. Webhook event `message.postback`, sent as a `POST` to your endpoint ```json { "webhooks": { "message.postback": { "post": { "tags": [ "Webhooks" ], "summary": "Message postback", "description": "Sent when the person taps a postback button, a persistent menu item or an ice breaker.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "message.postback" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessagePostbackEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "MessagePostbackEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "message.postback" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/MessagePostback" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "MessagePostback": { "type": "object", "properties": { "messageId": { "type": [ "string", "null" ], "description": "The tap's id on Instagram. null on Facebook.", "examples": [ null ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The connected Facebook Page or Instagram account." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "conversationId": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "senderId": { "type": "string", "description": "The platform's id for the sending side.", "examples": [ "6845123987456321" ] }, "recipientId": { "type": "string", "description": "The platform's id for the receiving side.", "examples": [ "17841452906318274" ] }, "title": { "type": [ "string", "null" ], "description": "The text the person tapped.", "examples": [ "Order status" ] }, "payload": { "type": [ "string", "null" ], "description": "The value you set on the button, menu item or ice breaker.", "examples": [ "ORDER_STATUS" ] }, "sentAt": { "type": "string", "format": "date-time", "description": "When the event happened on the platform, in ISO 8601.", "examples": [ "2027-03-15T14:05:11.000Z" ] } }, "required": [ "messageId", "accountId", "platform", "conversationId", "senderId", "recipientId", "title", "payload", "sentAt" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Message Reaction (/docs/api-reference/webhook-events/message-reaction) Sent when the person reacts to a message, or removes their reaction. Webhook event `message.reaction`, sent as a `POST` to your endpoint ```json { "webhooks": { "message.reaction": { "post": { "tags": [ "Webhooks" ], "summary": "Message reaction", "description": "Sent when the person reacts to a message, or removes their reaction.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "message.reaction" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageReactionEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "MessageReactionEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "message.reaction" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/MessageReaction" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "MessageReaction": { "type": "object", "properties": { "messageId": { "type": "string", "description": "The message the person reacted to.", "examples": [ "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDUyOTA2MzE4Mjc0OjM0MDI4MjM2Njg0" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The connected Facebook Page or Instagram account." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "conversationId": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "senderId": { "type": "string", "description": "The platform's id for the sending side.", "examples": [ "6845123987456321" ] }, "recipientId": { "type": "string", "description": "The platform's id for the receiving side.", "examples": [ "17841452906318274" ] }, "action": { "type": "string", "enum": [ "react", "unreact" ], "description": "react when the person adds a reaction, unreact when they remove it.", "examples": [ "react" ] }, "reaction": { "type": [ "string", "null" ], "description": "The reaction's name, such as love or like.", "examples": [ "love" ] }, "emoji": { "type": [ "string", "null" ], "description": "The reaction's emoji. Null when the platform does not send one.", "examples": [ "❤" ] }, "sentAt": { "type": "string", "format": "date-time", "description": "When the event happened on the platform, in ISO 8601.", "examples": [ "2027-03-15T14:05:11.000Z" ] } }, "required": [ "messageId", "accountId", "platform", "conversationId", "senderId", "recipientId", "action", "reaction", "emoji", "sentAt" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Message Read (/docs/api-reference/webhook-events/message-read) Sent when the person reads messages the account sent. It names no message ids, so use watermark. Webhook event `message.read`, sent as a `POST` to your endpoint ```json { "webhooks": { "message.read": { "post": { "tags": [ "Webhooks" ], "summary": "Message read", "description": "Sent when the person reads messages the account sent. It names no message ids, so use watermark.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "message.read" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageReadEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "MessageReadEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "message.read" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/MessageReadReceipt" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "MessageReadReceipt": { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The connected Facebook Page or Instagram account." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "conversationId": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "senderId": { "type": "string", "description": "The platform's id for the sending side.", "examples": [ "6845123987456321" ] }, "recipientId": { "type": "string", "description": "The platform's id for the receiving side.", "examples": [ "17841452906318274" ] }, "watermark": { "type": [ "integer", "null" ], "description": "Unix time in milliseconds. Every message the account sent in this conversation before it is covered. null when the platform sends none.", "examples": [ 1805119651000 ] }, "sentAt": { "type": "string", "format": "date-time", "description": "When the event happened on the platform, in ISO 8601.", "examples": [ "2027-03-15T14:05:11.000Z" ] } }, "required": [ "accountId", "platform", "conversationId", "senderId", "recipientId", "watermark", "sentAt" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Message Received (/docs/api-reference/webhook-events/message-received) Sent when someone sends a message to a connected Facebook Page or Instagram account. Webhook event `message.received`, sent as a `POST` to your endpoint ```json { "webhooks": { "message.received": { "post": { "tags": [ "Webhooks" ], "summary": "Message received", "description": "Sent when someone sends a message to a connected Facebook Page or Instagram account.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "message.received" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageReceivedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "MessageReceivedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "message.received" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/InboxMessage" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "InboxMessage": { "type": "object", "properties": { "id": { "type": "string", "description": "The platform's id for the message, the same id it has in the inbox endpoints.", "examples": [ "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDUyOTA2MzE4Mjc0OjM0MDI4MjM2Njg0" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The connected Facebook Page or Instagram account." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "conversationId": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "senderId": { "type": "string", "description": "The platform's id for the sending side.", "examples": [ "6845123987456321" ] }, "recipientId": { "type": "string", "description": "The platform's id for the receiving side.", "examples": [ "17841452906318274" ] }, "text": { "type": [ "string", "null" ], "description": "The message text, or null when it has only attachments.", "examples": [ "Hi, is the large size back in stock?" ] }, "hasAttachments": { "type": "boolean", "description": "true when the message has attachments. Read them through the inbox endpoints.", "examples": [ false ] }, "sentAt": { "type": "string", "format": "date-time", "description": "When the event happened on the platform, in ISO 8601.", "examples": [ "2027-03-15T14:05:11.000Z" ] } }, "required": [ "id", "accountId", "platform", "conversationId", "senderId", "recipientId", "text", "hasAttachments", "sentAt" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Message Sent (/docs/api-reference/webhook-events/message-sent) Sent when a connected Facebook Page or Instagram account sends a message, through Onepostly or the platform's own inbox. senderId is the account. Webhook event `message.sent`, sent as a `POST` to your endpoint ```json { "webhooks": { "message.sent": { "post": { "tags": [ "Webhooks" ], "summary": "Message sent", "description": "Sent when a connected Facebook Page or Instagram account sends a message, through Onepostly or the platform's own inbox. senderId is the account.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "message.sent" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageSentEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "MessageSentEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "message.sent" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/InboxMessage" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "InboxMessage": { "type": "object", "properties": { "id": { "type": "string", "description": "The platform's id for the message, the same id it has in the inbox endpoints.", "examples": [ "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDUyOTA2MzE4Mjc0OjM0MDI4MjM2Njg0" ] }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The connected Facebook Page or Instagram account." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." }, "conversationId": { "type": "string", "description": "A conversation id from List Conversations, Create Conversation or an inbox webhook.", "examples": [ "cnv_HEjYFMpANOkmDhP6W8cF57AbClWN8VKQgwy7yAKwY6vYtBIXoNSC44JrQldArbYX7qJPs" ] }, "senderId": { "type": "string", "description": "The platform's id for the sending side.", "examples": [ "6845123987456321" ] }, "recipientId": { "type": "string", "description": "The platform's id for the receiving side.", "examples": [ "17841452906318274" ] }, "text": { "type": [ "string", "null" ], "description": "The message text, or null when it has only attachments.", "examples": [ "Hi, is the large size back in stock?" ] }, "hasAttachments": { "type": "boolean", "description": "true when the message has attachments. Read them through the inbox endpoints.", "examples": [ false ] }, "sentAt": { "type": "string", "format": "date-time", "description": "When the event happened on the platform, in ISO 8601.", "examples": [ "2027-03-15T14:05:11.000Z" ] } }, "required": [ "id", "accountId", "platform", "conversationId", "senderId", "recipientId", "text", "hasAttachments", "sentAt" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Cancelled (/docs/api-reference/webhook-events/post-cancelled) Sent when you cancel a scheduled post with DELETE /v1/posts/{id} before it publishes. Webhook event `post.cancelled`, sent as a `POST` to your endpoint ```json { "webhooks": { "post.cancelled": { "post": { "tags": [ "Webhooks" ], "summary": "Post cancelled", "description": "Sent when you cancel a scheduled post with DELETE /v1/posts/{id} before it publishes.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "post.cancelled" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostCancelledEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "PostCancelledEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "post.cancelled" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/Post" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Created (/docs/api-reference/webhook-events/post-created) Sent when a post the account made outside Onepostly is found for the first time. Webhook event `post.created`, sent as a `POST` to your endpoint ```json { "webhooks": { "post.created": { "post": { "tags": [ "Webhooks" ], "summary": "Post created", "description": "Sent when a post the account made outside Onepostly is found for the first time.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "post.created" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostCreatedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "PostCreatedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "post.created" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/Post" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Deleted (/docs/api-reference/webhook-events/post-deleted) Sent when you delete a published post with DELETE /v1/posts/{id}, or when a post made outside Onepostly is gone from the platform. Webhook event `post.deleted`, sent as a `POST` to your endpoint ```json { "webhooks": { "post.deleted": { "post": { "tags": [ "Webhooks" ], "summary": "Post deleted", "description": "Sent when you delete a published post with DELETE /v1/posts/{id}, or when a post made outside Onepostly is gone from the platform.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "post.deleted" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostDeletedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "PostDeletedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "post.deleted" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/Post" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Failed (/docs/api-reference/webhook-events/post-failed) Sent when a post fails to publish. The post's error says why. Webhook event `post.failed`, sent as a `POST` to your endpoint ```json { "webhooks": { "post.failed": { "post": { "tags": [ "Webhooks" ], "summary": "Post failed", "description": "Sent when a post fails to publish. The post's error says why.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "post.failed" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostFailedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "PostFailedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "post.failed" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/Post" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Published (/docs/api-reference/webhook-events/post-published) Sent when a post is live on its platform. The object is the post, as Get Post returns it. Webhook event `post.published`, sent as a `POST` to your endpoint ```json { "webhooks": { "post.published": { "post": { "tags": [ "Webhooks" ], "summary": "Post published", "description": "Sent when a post is live on its platform. The object is the post, as Get Post returns it.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "post.published" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostPublishedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "PostPublishedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "post.published" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/Post" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Scheduled (/docs/api-reference/webhook-events/post-scheduled) Sent when a post is created with a future scheduledFor. The object is the post, as Get Post returns it. Webhook event `post.scheduled`, sent as a `POST` to your endpoint ```json { "webhooks": { "post.scheduled": { "post": { "tags": [ "Webhooks" ], "summary": "Post scheduled", "description": "Sent when a post is created with a future scheduledFor. The object is the post, as Get Post returns it.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "post.scheduled" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostScheduledEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "PostScheduledEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "post.scheduled" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/Post" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Post Updated (/docs/api-reference/webhook-events/post-updated) Sent when you edit a scheduled post with PATCH /v1/posts/{id}, when a TikTok post gets its public id, when a Facebook video gets its post id, or when a post made outside Onepostly changes. Webhook event `post.updated`, sent as a `POST` to your endpoint ```json { "webhooks": { "post.updated": { "post": { "tags": [ "Webhooks" ], "summary": "Post updated", "description": "Sent when you edit a scheduled post with PATCH /v1/posts/{id}, when a TikTok post gets its public id, when a Facebook video gets its post id, or when a post made outside Onepostly changes.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "post.updated" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostUpdatedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "PostUpdatedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "post.updated" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/Post" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "Post": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73" ] }, "groupId": { "type": [ "string", "null" ], "examples": [ "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45" ], "description": "Shared by the posts one Create Post request made. Null for posts published outside Onepostly." }, "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ] }, "platform": { "$ref": "#/components/schemas/Platform" }, "source": { "type": "string", "enum": [ "onepostly", "external" ], "description": "external for a post the account published outside Onepostly." }, "status": { "$ref": "#/components/schemas/PostStatus" }, "text": { "type": [ "string", "null" ], "description": "The post's text. Null for posts published outside Onepostly.", "examples": [ "Ship day" ] }, "mediaKind": { "$ref": "#/components/schemas/MediaKind", "description": "What the post is. An Instagram video post reads reel, because Instagram publishes it as a reel." }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" }, "description": "The post's media files, in order." }, "thread": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" }, "media": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFile" } } }, "required": [ "text", "media" ] }, "description": "Replies published under the first post, in order." }, "scheduledFor": { "type": [ "string", "null" ], "description": "Local date and time of the schedule in timezone. Null when not scheduled.", "examples": [ "2027-03-15T09:00:00" ] }, "timezone": { "type": [ "string", "null" ], "description": "IANA timezone of scheduledFor. Null when not scheduled.", "examples": [ "America/New_York" ] }, "options": { "type": "object", "properties": { "x": { "$ref": "#/components/schemas/XOptions" }, "instagram": { "$ref": "#/components/schemas/InstagramOptions" }, "facebook": { "$ref": "#/components/schemas/FacebookOptions" }, "threads": { "$ref": "#/components/schemas/ThreadsOptions" }, "linkedin": { "$ref": "#/components/schemas/LinkedInOptions" }, "youtube": { "$ref": "#/components/schemas/YouTubeOptions" }, "tiktok": { "$ref": "#/components/schemas/TikTokOptions" }, "pinterest": { "$ref": "#/components/schemas/PinterestOptions" }, "bluesky": { "$ref": "#/components/schemas/BlueskyOptions" } }, "description": "The platform options the post was created with, under the post's platform key as in Create Post. Only that one key is present. Empty when the post has no options, such as a post made outside Onepostly. New platforms can be added, so ignore a key you do not know.", "examples": [ { "tiktok": { "privacyLevel": "public_to_everyone", "allowComment": true, "allowDuet": false, "allowStitch": false } } ] }, "platformPostId": { "type": [ "string", "null" ], "description": "The platform's own id for the post. Null until it is published.", "examples": [ "17895695668004550" ] }, "url": { "type": [ "string", "null" ], "description": "Public link to the post on the platform.", "examples": [ "https://x.com/you/status/17895695668004550" ] }, "error": { "type": [ "object", "null" ], "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { "type": "string" } }, "required": [ "code", "message" ], "description": "Why the post failed. Null otherwise." }, "publishedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the post went live on the platform. Null until then." }, "metrics": { "oneOf": [ { "$ref": "#/components/schemas/PostMetrics" }, { "type": "null" } ], "description": "Lifetime metrics, or null before the first reading." }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "groupId", "accountId", "platform", "source", "status", "text", "mediaKind", "media", "thread", "scheduledFor", "timezone", "options", "platformPostId", "url", "error", "publishedAt", "metrics", "createdAt", "updatedAt" ] }, "PostMetrics": { "type": "object", "properties": { "impressions": { "type": [ "integer", "null" ] }, "reach": { "type": [ "integer", "null" ] }, "likes": { "type": [ "integer", "null" ] }, "comments": { "type": [ "integer", "null" ] }, "shares": { "type": [ "integer", "null" ] }, "saves": { "type": [ "integer", "null" ] }, "views": { "type": [ "integer", "null" ] }, "engagement": { "type": [ "integer", "null" ] } }, "required": [ "impressions", "reach", "likes", "comments", "shares", "saves", "views", "engagement" ], "description": "Lifetime metrics. A metric the platform does not report is null." }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "BlueskyOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Bluesky post, or its at:// URI. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link card for the first post. Text posts only. A post with media returns VALIDATION_ERROR." }, "langs": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 16 }, "maxItems": 3, "description": "Language tags for the post, such as en or pt. Up to 3." } }, "additionalProperties": false, "description": "Options for Bluesky accounts." }, "PinterestOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link for the post. Must use HTTPS. Link shorteners are rejected." }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Pin title, up to 100 characters. Defaults to the first line of the post text." }, "description": { "type": "string", "maxLength": 800, "description": "Pin description, up to 800 characters. Defaults to the post text." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content and adds Pinterest's AI-modified label." }, "boardId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Board to publish to, from List Pinterest Boards. Required." }, "coverImageUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Cover image URL. Video pins only. An image pin returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Pinterest accounts." }, "TikTokOptions": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 4000, "description": "Photo posts: description, up to 4,000 characters. Defaults to the post text. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content." }, "privacyLevel": { "type": "string", "enum": [ "public_to_everyone", "mutual_follow_friends", "follower_of_creator", "self_only" ], "description": "Who can see the post. Required. Use one of the privacyLevelOptions from Get TikTok Creator Info. Another value returns INVALID_PRIVACY_LEVEL." }, "allowComment": { "type": "boolean", "description": "Required. true lets viewers comment, false turns comments off. true returns INTERACTION_DISABLED when the creator turned comments off." }, "allowDuet": { "type": "boolean", "description": "Videos: required. true lets viewers duet, false turns duets off. true returns INTERACTION_DISABLED when the creator turned duets off. A photo post returns VALIDATION_ERROR." }, "allowStitch": { "type": "boolean", "description": "Videos: required. true lets viewers stitch, false turns stitches off. true returns INTERACTION_DISABLED when the creator turned stitches off. A photo post returns VALIDATION_ERROR." }, "brandOrganicToggle": { "type": "boolean", "description": "Declares that the content promotes the creator's own brand." }, "brandContentToggle": { "type": "boolean", "description": "Declares a paid partnership with a third party." }, "videoCoverTimestampMs": { "type": "integer", "minimum": 0, "maximum": 600000, "description": "Videos: cover frame position, in milliseconds. A photo post returns VALIDATION_ERROR." }, "photoCoverIndex": { "type": "integer", "minimum": 0, "maximum": 34, "description": "Photo posts: position of the cover photo, starting at 0. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." }, "autoAddMusic": { "type": "boolean", "description": "Photo posts: adds recommended music automatically. Only with mediaKind image or multi_image. A video returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for TikTok accounts." }, "YouTubeOptions": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Video title, up to 100 characters. Defaults to the post text, shortened to fit." }, "description": { "type": "string", "maxLength": 5000, "description": "Video description, up to 5,000 characters. Defaults to the post text." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 10000, "description": "Comment published right after the video, up to 10,000 characters." }, "privacyStatus": { "type": "string", "enum": [ "public", "private", "unlisted" ], "description": "public, private or unlisted. Defaults to public." }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "maxItems": 30, "description": "Video tags. Up to 30, with at most 500 characters combined." }, "categoryId": { "type": "string", "minLength": 1, "maxLength": 3, "description": "Video category id, such as 22 or 10." }, "madeForKids": { "type": "boolean", "description": "Declares the video as made for kids under COPPA." }, "containsSyntheticMedia": { "type": "boolean", "description": "Discloses realistic content that is AI-generated or altered." } }, "additionalProperties": false, "description": "Options for YouTube accounts." }, "LinkedInOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 1250, "description": "Comment published right after the post, up to 1,250 characters." } }, "additionalProperties": false, "description": "Options for LinkedIn accounts." }, "ThreadsOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "replyToPostId": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Post to reply to. Send the pst_ id of a published Threads post, or the Threads post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Reply published right after the post, up to 500 characters." }, "topicTag": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Topic tag of 1 to 50 characters, without periods or ampersands. Replaces the tag taken from the post's hashtags." } }, "additionalProperties": false, "description": "Options for Threads accounts." }, "FacebookOptions": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Link preview for a text post. Text posts only. A post with media returns VALIDATION_ERROR." }, "firstComment": { "type": "string", "minLength": 1, "maxLength": 8000, "description": "Comment published right after the post, up to 8,000 characters. A story returns VALIDATION_ERROR." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US, that limit who sees the post. Up to 25. Only with mediaKind text or multi_image. Other media kinds return VALIDATION_ERROR." }, "carouselCards": { "type": "array", "items": { "type": "object", "properties": { "link": { "type": "string", "maxLength": 2048, "format": "uri" }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "description": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "link" ] }, "minItems": 2, "maxItems": 10, "description": "Link cards for a multi-link carousel, one per image in order. Requires mediaKind multi_image with the same number of images." }, "carouselLink": { "type": "string", "maxLength": 2048, "format": "uri", "description": "See more link on the carousel's end card. Used with carouselCards." }, "textFormatPresetId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Preset id for a large-text background. Text-only feed posts." }, "reelTitle": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Reel title, shown apart from the caption, up to 100 characters. Only with mediaKind reel." } }, "additionalProperties": false, "description": "Options for Facebook accounts." }, "InstagramOptions": { "type": "object", "properties": { "firstComment": { "type": "string", "minLength": 1, "maxLength": 2200, "description": "Comment published right after the post, up to 2,200 characters. A story returns VALIDATION_ERROR." }, "isAiGenerated": { "type": "boolean", "description": "Discloses AI-generated content. A story returns VALIDATION_ERROR." }, "userTags": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string", "minLength": 1, "maxLength": 64 }, "x": { "type": "number", "minimum": 0, "maximum": 1 }, "y": { "type": "number", "minimum": 0, "maximum": 1 } }, "required": [ "username" ] }, "maxItems": 20, "description": "Users to tag. Image posts need x and y positions, from 0 to 1, for each tag." }, "collaborators": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 3, "description": "Up to 3 collaborator usernames. Feed images, reels and carousels. A story returns VALIDATION_ERROR." }, "thumbOffset": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "Reels: cover frame position, in milliseconds. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "coverUrl": { "type": "string", "maxLength": 2048, "format": "uri", "description": "Reels: custom cover image URL. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioName": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reels: new name for the original audio. Instagram allows one rename. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "shareToFeed": { "type": "boolean", "description": "Reels: true shows the reel in the feed and the Reels tab, false in the Reels tab only. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialReel": { "type": "boolean", "description": "Reels: true publishes a trial reel, shown to non-followers first. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "trialGraduationStrategy": { "type": "string", "enum": [ "manual", "ss_performance" ], "description": "Reels: how a trial reel graduates. Defaults to manual. Requires trialReel. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Reels: catalog audio id from Search Instagram Audio. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "audioVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the added audio, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "videoVolume": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Reels: volume of the original video sound, from 1 to 100. Defaults to 100. Requires audioId. Only with mediaKind reel or video, which both publish a reel. Other media kinds return VALIDATION_ERROR." }, "locationId": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Id of a Facebook Page with location data, used as the post location. A story returns VALIDATION_ERROR." }, "isPaidPartnership": { "type": "boolean", "description": "Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. A story returns VALIDATION_ERROR." }, "brandedContentSponsors": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 64 }, "maxItems": 2, "description": "Up to 2 sponsor usernames or numeric user ids. Adds the paid partnership label. Requires an account connected with loginMethod facebook_login, or the request returns VALIDATION_ERROR. Feed posts, reels and carousels. A story returns VALIDATION_ERROR." }, "commentsEnabled": { "type": "boolean", "description": "false turns comments off right after publishing, when Instagram allows it. A story returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for Instagram accounts." }, "XOptions": { "type": "object", "properties": { "quotePostId": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Post to quote. Send the pst_ id of a published X post, or the X post id. A pst_ id of a post that is not live returns POST_NOT_PUBLISHED." }, "geoRestriction": { "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$" }, "minItems": 1, "maxItems": 25, "description": "Uppercase two-letter country codes, such as US. Up to 25. Media is hidden outside these countries while the text stays visible everywhere. Applies to every post of the thread that has media. A post with no media in the first post or its thread returns VALIDATION_ERROR." } }, "additionalProperties": false, "description": "Options for X accounts." }, "MediaFile": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } }, "required": [ "url" ], "examples": [ { "url": "https://cdn.onepostly.com/media/product.jpg" } ] }, "MediaKind": { "anyOf": [ { "type": "string", "enum": [ "text", "image", "multi_image", "video", "reel", "document", "stories" ] }, { "type": "string" } ], "description": "What the media is. New values can be added, so handle a value you do not know.", "examples": [ "image" ] }, "PostStatus": { "anyOf": [ { "type": "string", "enum": [ "scheduled", "publishing", "published", "failed", "cancelled", "deleted" ] }, { "type": "string" } ], "description": "scheduled waits for scheduledFor. publishing is on its way to the platform. published, failed, cancelled and deleted are final. New values can be added, so handle a value you do not know." }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Review Received (/docs/api-reference/webhook-events/review-received) Sent when someone recommends a connected Facebook Page, or says they do not. Webhook event `review.received`, sent as a `POST` to your endpoint ```json { "webhooks": { "review.received": { "post": { "tags": [ "Webhooks" ], "summary": "Review received", "description": "Sent when someone recommends a connected Facebook Page, or says they do not.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "review.received" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReviewReceivedEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "ReviewReceivedEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "review.received" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/ReceivedPageReview" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "ReceivedPageReview": { "allOf": [ { "$ref": "#/components/schemas/PageReview" }, { "type": "object", "properties": { "accountId": { "type": "string", "examples": [ "acc_1699f4157fb643f49d2ac447491f32a8" ], "description": "The connected Facebook Page." }, "platform": { "$ref": "#/components/schemas/Platform", "description": "The platform of the account." } }, "required": [ "accountId", "platform" ] } ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "PageReview": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "1234567890" ] }, "recommendation": { "type": [ "string", "null" ], "enum": [ "positive", "negative", null ], "description": "Whether the reviewer recommends the Page. `null` on older star-only reviews.", "examples": [ "positive" ] }, "rating": { "type": [ "number", "null" ], "description": "The legacy 1 to 5 star rating. `null` on reviews without stars.", "examples": [ 5 ] }, "text": { "type": [ "string", "null" ], "description": "The review text. Null for a review without text.", "examples": [ "Great service!" ] }, "reviewerName": { "type": [ "string", "null" ], "description": "The reviewer's name. Null when Facebook does not share it.", "examples": [ "Jane Doe" ] }, "createdAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When the review was posted. Null when Facebook does not report it.", "examples": [ "2026-08-25T10:00:00.000Z" ] } }, "required": [ "id", "recommendation", "rating", "text", "reviewerName", "createdAt" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Test Event (/docs/api-reference/webhook-events/webhook-test) Sent only by Send Test Event, whatever the webhook subscribes to. Webhook event `webhook.test`, sent as a `POST` to your endpoint ```json { "webhooks": { "webhook.test": { "post": { "tags": [ "Webhooks" ], "summary": "Test event", "description": "Sent only by Send Test Event, whatever the webhook subscribes to.", "security": [], "x-internal": true, "parameters": [ { "$ref": "#/components/parameters/OnepostlySignature" }, { "schema": { "type": "string", "enum": [ "webhook.test" ], "description": "The event name, the same as type." }, "required": true, "description": "The event name, the same as type.", "name": "Onepostly-Event", "in": "header" }, { "$ref": "#/components/parameters/OnepostlyEventId" }, { "$ref": "#/components/parameters/OnepostlyDelivery" }, { "$ref": "#/components/parameters/UserAgent" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookTestEvent" } } } }, "responses": { "2XX": { "description": "Acknowledges the delivery. Answer within 10 seconds, and do slow work after you answer." }, "default": { "description": "Any other answer fails the attempt, and so does no answer within 10 seconds. After a 408, 429 or 5xx, a timeout or a network error the event is sent again. Any other status, a redirect included, ends the delivery." } } } } }, "components": { "schemas": { "WebhookTestEvent": { "allOf": [ { "$ref": "#/components/schemas/WebhookEventBase" }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "webhook.test" ], "description": "The event name." }, "data": { "type": "object", "properties": { "object": { "$ref": "#/components/schemas/WebhookTest" } }, "required": [ "object" ], "description": "Holds object, the object the event is about, as it was when the event happened." } }, "required": [ "type", "data" ] } ] }, "WebhookTest": { "type": "object", "properties": { "message": { "type": "string", "examples": [ "Onepostly webhook test event" ] }, "webhookId": { "type": "string", "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ], "description": "The webhook the test was sent to." } }, "required": [ "message", "webhookId" ] }, "WebhookEventBase": { "type": "object", "properties": { "id": { "type": "string", "description": "The event id, starting with evt_. It stays the same on every retry, so use it as your idempotency key.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created, in ISO 8601. It does not change between retries.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "organizationId": { "type": "string", "description": "The workspace the event belongs to.", "examples": [ "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b" ] } }, "required": [ "id", "createdAt", "organizationId" ] } }, "parameters": { "UserAgent": { "schema": { "type": "string", "description": "Always Onepostly-Webhooks/1.0.", "examples": [ "Onepostly-Webhooks/1.0" ] }, "required": true, "description": "Always Onepostly-Webhooks/1.0.", "name": "User-Agent", "in": "header" }, "OnepostlyDelivery": { "schema": { "type": "string", "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "description": "The delivery id, as List Deliveries shows it. It stays the same across attempts.", "name": "Onepostly-Delivery", "in": "header" }, "OnepostlyEventId": { "schema": { "type": "string", "description": "The event id, the same as id.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "required": true, "description": "The event id, the same as id.", "name": "Onepostly-Event-Id", "in": "header" }, "OnepostlySignature": { "schema": { "type": "string", "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "examples": [ "t=1805101202,v1=48267c482b923179ab3b38f14e593896bfa7fde216b400b4ad697749d3ba95ef" ] }, "required": true, "description": "t is the Unix time in seconds and v1 the hex HMAC-SHA256 of t, a period and the raw body, keyed with the webhook's secret. Verify it before you trust the body.", "name": "Onepostly-Signature", "in": "header" } } } } ``` # Create Webhook (/docs/api-reference/webhooks/create-webhook) Registers an endpoint for events. Each delivery is signed with the secret in the Onepostly-Signature header. `POST https://api.onepostly.com/v1/webhooks` ```json { "paths": { "/v1/webhooks": { "post": { "operationId": "createWebhook", "tags": [ "Webhooks" ], "summary": "Create webhook", "description": "Registers an endpoint for events. Each delivery is signed with the secret in the Onepostly-Signature header.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateWebhookBody" } } } }, "responses": { "201": { "description": "Created webhook. The signing secret is shown only in this response.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookWithSecret" }, "example": { "id": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "name": "Production", "url": "https://example.com/hooks/onepostly", "enabled": true, "events": [ "post.published", "post.failed", "account.expired", "account.revoked" ], "createdAt": "2027-03-14T16:20:00.000Z", "updatedAt": "2027-03-14T16:20:00.000Z", "secret": "q3Vt8kRz1mXo5bJw7nLc2yHd9sAf4gPe" } } } }, "400": { "description": "The request is invalid, for example when url is not a public HTTPS address (VALIDATION_ERROR)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "409": { "$ref": "#/components/responses/ConflictReplayable" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WebhooksApi } from \"@onepostly/sdk\";\n\nconst webhooksApi = new WebhooksApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await webhooksApi.createWebhook({\n createWebhookBody: {\n \"name\": \"Production\",\n \"url\": \"https://example.com/hooks/onepostly\",\n \"events\": [\n \"post.published\",\n \"post.failed\",\n \"account.expired\",\n \"account.revoked\"\n ]\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.webhooks_api import WebhooksApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n webhooks_api = WebhooksApi(api_client)\n response = await webhooks_api.create_webhook(\n create_webhook_body={\n \"name\": \"Production\",\n \"url\": \"https://example.com/hooks/onepostly\",\n \"events\": [\n \"post.published\",\n \"post.failed\",\n \"account.expired\",\n \"account.revoked\"\n ]\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/webhooks\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"name\": \"Production\",\n \"url\": \"https://example.com/hooks/onepostly\",\n \"events\": [\n \"post.published\",\n \"post.failed\",\n \"account.expired\",\n \"account.revoked\"\n ]\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "WebhookWithSecret": { "allOf": [ { "$ref": "#/components/schemas/Webhook" }, { "type": "object", "properties": { "secret": { "type": "string", "description": "Signing secret. It is shown only here; store it now.", "examples": [ "s7a9Kx2mQ8vB4nR6tY3wZ1pL5oN0uMf" ] } }, "required": [ "secret" ] } ] }, "Webhook": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "name": { "type": "string", "examples": [ "Post events" ] }, "url": { "type": "string", "format": "uri", "examples": [ "https://example.com/hooks/onepostly" ] }, "enabled": { "type": "boolean", "description": "false while the webhook is paused. A paused webhook receives no events.", "examples": [ true ] }, "events": { "type": "array", "items": { "type": "string" }, "description": "Event types the webhook receives, as you set them. [\"*\"] means every event type, including ones added later.", "examples": [ [ "post.published" ] ] }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "name", "url", "enabled", "events", "createdAt", "updatedAt" ] }, "CreateWebhookBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 120, "examples": [ "Post events" ] }, "url": { "type": "string", "maxLength": 2048, "format": "uri", "description": "HTTPS URL that receives the events.", "examples": [ "https://example.com/hooks/onepostly" ] }, "secret": { "type": "string", "minLength": 16, "maxLength": 128, "description": "Signing secret to use. One is generated when you leave it out." }, "events": { "type": "array", "items": { "type": "string", "enum": [ "*", "post.scheduled", "post.published", "post.failed", "post.cancelled", "post.deleted", "post.updated", "post.created", "comment.created", "comment.deleted", "comment.received", "message.received", "message.sent", "message.delivered", "message.read", "message.deleted", "message.reaction", "message.postback", "review.received", "engagement.liked", "engagement.unliked", "engagement.bookmarked", "engagement.unbookmarked", "engagement.reposted", "engagement.unreposted", "account.connected", "account.disconnected", "account.expiring", "account.expired", "account.revoked", "webhook.test" ] }, "minItems": 1, "maxItems": 30, "description": "Event types to receive, from List Event Types. [\"*\"] receives every event type, including ones added later. \"*\" must be the only item, or the request returns VALIDATION_ERROR.", "examples": [ [ "post.published", "post.failed" ], [ "*" ] ] }, "enabled": { "type": "boolean", "default": true, "description": "false creates the webhook paused." } }, "required": [ "name", "url", "events" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ConflictReplayable": { "description": "The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Delete Webhook (/docs/api-reference/webhooks/delete-webhook) Deletes a webhook and its delivery history. `DELETE https://api.onepostly.com/v1/webhooks/{id}` ```json { "paths": { "/v1/webhooks/{id}": { "delete": { "operationId": "deleteWebhook", "tags": [ "Webhooks" ], "summary": "Delete webhook", "description": "Deletes a webhook and its delivery history.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/WebhookId" } ], "responses": { "204": { "description": "Deleted", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No webhook with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WebhooksApi } from \"@onepostly/sdk\";\n\nconst webhooksApi = new WebhooksApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await webhooksApi.deleteWebhook({\n id: \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.webhooks_api import WebhooksApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n webhooks_api = WebhooksApi(api_client)\n response = await webhooks_api.delete_webhook(\n \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X DELETE \"https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] } }, "parameters": { "WebhookId": { "schema": { "type": "string", "minLength": 1, "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Delivery (/docs/api-reference/webhooks/get-webhook-delivery) Returns one delivery with the body that is sent. `GET https://api.onepostly.com/v1/webhooks/{id}/deliveries/{deliveryId}` ```json { "paths": { "/v1/webhooks/{id}/deliveries/{deliveryId}": { "get": { "operationId": "getWebhookDelivery", "tags": [ "Webhooks" ], "summary": "Get delivery", "description": "Returns one delivery with the body that is sent.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/WebhookId" }, { "$ref": "#/components/parameters/DeliveryId" } ], "responses": { "200": { "description": "Delivery", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookDeliveryDetail" }, "example": { "id": "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49", "webhookId": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "eventId": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72", "eventType": "post.published", "status": "success", "attempts": 1, "responseStatus": 200, "lastError": null, "createdAt": "2027-03-15T09:00:04.412Z", "deliveredAt": "2027-03-15T09:00:04.987Z", "payload": { "id": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72", "type": "post.published", "createdAt": "2027-03-15T09:00:04.412Z", "organizationId": "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b", "data": { "object": { "id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73", "groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45", "accountId": "acc_YOUR_X_ACCOUNT_ID", "platform": "x", "source": "onepostly", "status": "published", "text": "New release notes are up.", "mediaKind": "text", "media": [], "thread": [], "scheduledFor": null, "timezone": null, "options": {}, "platformPostId": "1900876543210987654", "url": "https://x.com/i/web/status/1900876543210987654", "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" } } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No webhook with this id, or the webhook has no delivery with this deliveryId (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WebhooksApi } from \"@onepostly/sdk\";\n\nconst webhooksApi = new WebhooksApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await webhooksApi.getWebhookDelivery({\n id: \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n deliveryId: \"dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.webhooks_api import WebhooksApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n webhooks_api = WebhooksApi(api_client)\n response = await webhooks_api.get_webhook_delivery(\n \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n \"dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58/deliveries/dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "WebhookDeliveryDetail": { "allOf": [ { "$ref": "#/components/schemas/WebhookDelivery" }, { "type": "object", "properties": { "payload": { "description": "The JSON body that is sent, exactly as it is signed." } } } ] }, "WebhookDelivery": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "webhookId": { "type": "string", "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "eventId": { "type": "string", "description": "The event's id, also sent as the Onepostly-Event-Id header.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "eventType": { "type": "string", "examples": [ "post.published" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "pending", "success", "failed" ] }, { "type": "string" } ], "description": "pending while attempts remain, then success or failed. New values can be added, so handle a value you do not know.", "examples": [ "success" ] }, "attempts": { "type": "integer", "description": "Times the event was sent to your endpoint so far.", "examples": [ 1 ] }, "responseStatus": { "type": [ "integer", "null" ], "description": "HTTP status your endpoint last answered with.", "examples": [ 200 ] }, "lastError": { "type": [ "string", "null" ], "description": "Why the last attempt failed. Null after a success." }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "deliveredAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When your endpoint accepted the event. Null until it does.", "examples": [ "2027-03-15T09:00:01.987Z" ] } }, "required": [ "id", "webhookId", "eventId", "eventType", "status", "attempts", "responseStatus", "lastError", "createdAt", "deliveredAt" ] } }, "parameters": { "DeliveryId": { "schema": { "type": "string", "minLength": 1, "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "name": "deliveryId", "in": "path" }, "WebhookId": { "schema": { "type": "string", "minLength": 1, "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Get Webhook (/docs/api-reference/webhooks/get-webhook) `GET https://api.onepostly.com/v1/webhooks/{id}` ```json { "paths": { "/v1/webhooks/{id}": { "get": { "operationId": "getWebhook", "tags": [ "Webhooks" ], "summary": "Get webhook", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/WebhookId" } ], "responses": { "200": { "description": "Webhook", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Webhook" }, "example": { "id": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "name": "Production", "url": "https://example.com/hooks/onepostly", "enabled": true, "events": [ "post.published", "post.failed", "account.expired", "account.revoked" ], "createdAt": "2027-03-14T16:20:00.000Z", "updatedAt": "2027-03-14T16:20:00.000Z" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No webhook with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WebhooksApi } from \"@onepostly/sdk\";\n\nconst webhooksApi = new WebhooksApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await webhooksApi.getWebhook({\n id: \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.webhooks_api import WebhooksApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n webhooks_api = WebhooksApi(api_client)\n response = await webhooks_api.get_webhook(\n \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Webhook": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "name": { "type": "string", "examples": [ "Post events" ] }, "url": { "type": "string", "format": "uri", "examples": [ "https://example.com/hooks/onepostly" ] }, "enabled": { "type": "boolean", "description": "false while the webhook is paused. A paused webhook receives no events.", "examples": [ true ] }, "events": { "type": "array", "items": { "type": "string" }, "description": "Event types the webhook receives, as you set them. [\"*\"] means every event type, including ones added later.", "examples": [ [ "post.published" ] ] }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "name", "url", "enabled", "events", "createdAt", "updatedAt" ] } }, "parameters": { "WebhookId": { "schema": { "type": "string", "minLength": 1, "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Deliveries (/docs/api-reference/webhooks/list-webhook-deliveries) Lists a webhook's deliveries, newest first. `GET https://api.onepostly.com/v1/webhooks/{id}/deliveries` ```json { "paths": { "/v1/webhooks/{id}/deliveries": { "get": { "operationId": "listWebhookDeliveries", "tags": [ "Webhooks" ], "summary": "List deliveries", "description": "Lists a webhook's deliveries, newest first.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/WebhookId" }, { "$ref": "#/components/parameters/Limit50Max100" }, { "$ref": "#/components/parameters/Cursor" }, { "schema": { "type": "string", "format": "date-time", "description": "Only deliveries made at or after this time. Defaults to 7 days before until. Deliveries are kept for your plan's log retention, so an earlier time starts at the oldest kept delivery." }, "required": false, "description": "Only deliveries made at or after this time. Defaults to 7 days before until. Deliveries are kept for your plan's log retention, so an earlier time starts at the oldest kept delivery.", "name": "since", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "Only deliveries made before this time. Defaults to now." }, "required": false, "description": "Only deliveries made before this time. Defaults to now.", "name": "until", "in": "query" }, { "schema": { "type": "string", "description": "Comma-separated statuses to include: pending, success, failed. Omit it for every status." }, "required": false, "description": "Comma-separated statuses to include: pending, success, failed. Omit it for every status.", "name": "status", "in": "query" }, { "schema": { "type": "string", "maxLength": 120, "description": "Only deliveries whose event type or event id starts with this text." }, "required": false, "description": "Only deliveries whose event type or event id starts with this text.", "name": "q", "in": "query" }, { "schema": { "type": "string", "description": "Comma-separated extras to add to the response: facets, histogram." }, "required": false, "description": "Comma-separated extras to add to the response: facets, histogram.", "name": "include", "in": "query" } ], "responses": { "200": { "description": "Deliveries", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/WebhookDelivery" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." }, "facets": { "type": "object", "properties": { "status": { "type": "array", "items": { "type": "object", "properties": { "status": { "type": "string" }, "count": { "type": "integer" } }, "required": [ "status", "count" ] } } }, "required": [ "status" ], "description": "Counts per status. Present when include has facets." }, "histogram": { "type": "array", "items": { "type": "object", "properties": { "bucket": { "type": "string" }, "success": { "type": "integer" }, "failed": { "type": "integer" } }, "required": [ "bucket", "success", "failed" ] }, "description": "Successes and failures over time. Present when include has histogram." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b03", "webhookId": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "eventId": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a03", "eventType": "account.revoked", "status": "failed", "attempts": 5, "responseStatus": 503, "lastError": "HTTP 503", "createdAt": "2027-03-15T11:00:00.318Z", "deliveredAt": null }, { "id": "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49", "webhookId": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "eventId": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72", "eventType": "post.published", "status": "success", "attempts": 1, "responseStatus": 200, "lastError": null, "createdAt": "2027-03-15T09:00:04.412Z", "deliveredAt": "2027-03-15T09:00:04.987Z" }, { "id": "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b02", "webhookId": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "eventId": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a02", "eventType": "post.failed", "status": "success", "attempts": 2, "responseStatus": 200, "lastError": null, "createdAt": "2027-03-15T09:00:02.205Z", "deliveredAt": "2027-03-15T09:01:02.640Z" } ], "nextCursor": null, "hasMore": false } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "No webhook with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WebhooksApi } from \"@onepostly/sdk\";\n\nconst webhooksApi = new WebhooksApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await webhooksApi.listWebhookDeliveries({\n id: \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n limit: 20,\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.webhooks_api import WebhooksApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n webhooks_api = WebhooksApi(api_client)\n response = await webhooks_api.list_webhook_deliveries(\n \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n limit=20,\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58/deliveries?limit=20\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "WebhookDelivery": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "webhookId": { "type": "string", "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "eventId": { "type": "string", "description": "The event's id, also sent as the Onepostly-Event-Id header.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "eventType": { "type": "string", "examples": [ "post.published" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "pending", "success", "failed" ] }, { "type": "string" } ], "description": "pending while attempts remain, then success or failed. New values can be added, so handle a value you do not know.", "examples": [ "success" ] }, "attempts": { "type": "integer", "description": "Times the event was sent to your endpoint so far.", "examples": [ 1 ] }, "responseStatus": { "type": [ "integer", "null" ], "description": "HTTP status your endpoint last answered with.", "examples": [ 200 ] }, "lastError": { "type": [ "string", "null" ], "description": "Why the last attempt failed. Null after a success." }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "deliveredAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When your endpoint accepted the event. Null until it does.", "examples": [ "2027-03-15T09:00:01.987Z" ] } }, "required": [ "id", "webhookId", "eventId", "eventType", "status", "attempts", "responseStatus", "lastError", "createdAt", "deliveredAt" ] } }, "parameters": { "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max100": { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50, "description": "Items per page. Defaults to 50. Maximum 100.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 100.", "name": "limit", "in": "query" }, "WebhookId": { "schema": { "type": "string", "minLength": 1, "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Event Types (/docs/api-reference/webhooks/list-webhook-event-types) Lists every event type a webhook can subscribe to, with the group it belongs to. To receive all of them, including types added later, set events to ["*"]. `GET https://api.onepostly.com/v1/webhooks/events` ```json { "paths": { "/v1/webhooks/events": { "get": { "operationId": "listWebhookEventTypes", "tags": [ "Webhooks" ], "summary": "List event types", "description": "Lists every event type a webhook can subscribe to, with the group it belongs to. To receive all of them, including types added later, set events to [\"*\"].", "security": [ { "Bearer": [] } ], "responses": { "200": { "description": "Event types", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "examples": [ "post.published" ] }, "group": { "type": "string", "examples": [ "posts" ] } }, "required": [ "type", "group" ] } } }, "required": [ "data" ] }, "example": { "data": [ { "type": "post.scheduled", "group": "posts" }, { "type": "post.published", "group": "posts" }, { "type": "post.failed", "group": "posts" }, { "type": "post.cancelled", "group": "posts" }, { "type": "post.deleted", "group": "posts" }, { "type": "post.updated", "group": "posts" }, { "type": "post.created", "group": "posts" }, { "type": "comment.created", "group": "comments" }, { "type": "comment.deleted", "group": "comments" }, { "type": "comment.received", "group": "comments" }, { "type": "message.received", "group": "messages" }, { "type": "message.sent", "group": "messages" }, { "type": "message.delivered", "group": "messages" }, { "type": "message.read", "group": "messages" }, { "type": "message.deleted", "group": "messages" }, { "type": "message.reaction", "group": "messages" }, { "type": "message.postback", "group": "messages" }, { "type": "review.received", "group": "reviews" }, { "type": "engagement.liked", "group": "engagement" }, { "type": "engagement.unliked", "group": "engagement" }, { "type": "engagement.bookmarked", "group": "engagement" }, { "type": "engagement.unbookmarked", "group": "engagement" }, { "type": "engagement.reposted", "group": "engagement" }, { "type": "engagement.unreposted", "group": "engagement" }, { "type": "account.connected", "group": "accounts" }, { "type": "account.disconnected", "group": "accounts" }, { "type": "account.expiring", "group": "accounts" }, { "type": "account.expired", "group": "accounts" }, { "type": "account.revoked", "group": "accounts" } ] } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WebhooksApi } from \"@onepostly/sdk\";\n\nconst webhooksApi = new WebhooksApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await webhooksApi.listWebhookEventTypes();\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.webhooks_api import WebhooksApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n webhooks_api = WebhooksApi(api_client)\n response = await webhooks_api.list_webhook_event_types()\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/webhooks/events\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # List Webhooks (/docs/api-reference/webhooks/list-webhooks) Lists the workspace's webhooks, newest first. `GET https://api.onepostly.com/v1/webhooks` ```json { "paths": { "/v1/webhooks": { "get": { "operationId": "listWebhooks", "tags": [ "Webhooks" ], "summary": "List webhooks", "description": "Lists the workspace's webhooks, newest first.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/Limit50Max100" }, { "$ref": "#/components/parameters/Cursor" } ], "responses": { "200": { "description": "Webhooks", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Webhook" } }, "nextCursor": { "type": [ "string", "null" ], "description": "Cursor for the next page, or null on the last page." }, "hasMore": { "type": "boolean", "description": "True when another page follows this one." } }, "required": [ "data", "nextCursor", "hasMore" ] }, "example": { "data": [ { "id": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "name": "Production", "url": "https://example.com/hooks/onepostly", "enabled": true, "events": [ "post.published", "post.failed", "account.expired", "account.revoked" ], "createdAt": "2027-03-14T16:20:00.000Z", "updatedAt": "2027-03-14T16:20:00.000Z" }, { "id": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c02", "name": "Staging", "url": "https://staging.example.com/hooks/onepostly", "enabled": false, "events": [ "*" ], "createdAt": "2027-03-02T11:00:00.000Z", "updatedAt": "2027-03-10T08:30:00.000Z" } ], "nextCursor": null, "hasMore": false } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WebhooksApi } from \"@onepostly/sdk\";\n\nconst webhooksApi = new WebhooksApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await webhooksApi.listWebhooks({\n limit: 20,\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.webhooks_api import WebhooksApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n webhooks_api = WebhooksApi(api_client)\n response = await webhooks_api.list_webhooks(\n limit=20,\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X GET \"https://api.onepostly.com/v1/webhooks?limit=20\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Webhook": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "name": { "type": "string", "examples": [ "Post events" ] }, "url": { "type": "string", "format": "uri", "examples": [ "https://example.com/hooks/onepostly" ] }, "enabled": { "type": "boolean", "description": "false while the webhook is paused. A paused webhook receives no events.", "examples": [ true ] }, "events": { "type": "array", "items": { "type": "string" }, "description": "Event types the webhook receives, as you set them. [\"*\"] means every event type, including ones added later.", "examples": [ [ "post.published" ] ] }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "name", "url", "enabled", "events", "createdAt", "updatedAt" ] } }, "parameters": { "Cursor": { "schema": { "type": "string", "minLength": 1, "description": "The nextCursor of the previous page. Omit it for the first page." }, "required": false, "description": "The nextCursor of the previous page. Omit it for the first page.", "name": "cursor", "in": "query" }, "Limit50Max100": { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50, "description": "Items per page. Defaults to 50. Maximum 100.", "examples": [ 50 ] }, "required": false, "description": "Items per page. Defaults to 50. Maximum 100.", "name": "limit", "in": "query" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Validation error", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Retry Delivery (/docs/api-reference/webhooks/retry-webhook-delivery) Sends a finished delivery again, with the same event id and body. Use the event id to recognize a repeat. `POST https://api.onepostly.com/v1/webhooks/{id}/deliveries/{deliveryId}/retry` ```json { "paths": { "/v1/webhooks/{id}/deliveries/{deliveryId}/retry": { "post": { "operationId": "retryWebhookDelivery", "tags": [ "Webhooks" ], "summary": "Retry delivery", "description": "Sends a finished delivery again, with the same event id and body. Use the event id to recognize a repeat.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/WebhookId" }, { "$ref": "#/components/parameters/DeliveryId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "responses": { "200": { "description": "The delivery, queued again", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookDeliveryDetail" }, "example": { "id": "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b03", "webhookId": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "eventId": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a03", "eventType": "account.revoked", "status": "pending", "attempts": 0, "responseStatus": null, "lastError": null, "createdAt": "2027-03-15T11:00:00.318Z", "deliveredAt": null, "payload": { "id": "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a03", "type": "account.revoked", "createdAt": "2027-03-15T11:00:00.318Z", "organizationId": "5b0e7c1a-2f4d-4c8e-9a3b-6d1f0e2c4a7b", "data": { "object": { "id": "acc_YOUR_TIKTOK_ACCOUNT_ID", "platform": "tiktok", "handle": "yourbrand", "status": "revoked", "reason": "token_invalid", "tokenExpiresAt": "2027-03-16T09:00:00.000Z", "previousStatus": "active" } } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "description": "No webhook with this id, or the webhook has no delivery with this deliveryId (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The delivery is still being attempted (DELIVERY_IN_PROGRESS). Retry once it has finished. The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WebhooksApi } from \"@onepostly/sdk\";\n\nconst webhooksApi = new WebhooksApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await webhooksApi.retryWebhookDelivery({\n id: \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n deliveryId: \"dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b03\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.webhooks_api import WebhooksApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n webhooks_api = WebhooksApi(api_client)\n response = await webhooks_api.retry_webhook_delivery(\n \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n \"dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b03\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58/deliveries/dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b03/retry\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "WebhookDeliveryDetail": { "allOf": [ { "$ref": "#/components/schemas/WebhookDelivery" }, { "type": "object", "properties": { "payload": { "description": "The JSON body that is sent, exactly as it is signed." } } } ] }, "WebhookDelivery": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "webhookId": { "type": "string", "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "eventId": { "type": "string", "description": "The event's id, also sent as the Onepostly-Event-Id header.", "examples": [ "evt_7c41e09a5b3d4f2e8a6c1b9d0e3f5a72" ] }, "eventType": { "type": "string", "examples": [ "post.published" ] }, "status": { "anyOf": [ { "type": "string", "enum": [ "pending", "success", "failed" ] }, { "type": "string" } ], "description": "pending while attempts remain, then success or failed. New values can be added, so handle a value you do not know.", "examples": [ "success" ] }, "attempts": { "type": "integer", "description": "Times the event was sent to your endpoint so far.", "examples": [ 1 ] }, "responseStatus": { "type": [ "integer", "null" ], "description": "HTTP status your endpoint last answered with.", "examples": [ 200 ] }, "lastError": { "type": [ "string", "null" ], "description": "Why the last attempt failed. Null after a success." }, "createdAt": { "type": "string", "format": "date-time", "description": "When the event was created.", "examples": [ "2027-03-15T09:00:01.412Z" ] }, "deliveredAt": { "type": [ "string", "null" ], "format": "date-time", "description": "When your endpoint accepted the event. Null until it does.", "examples": [ "2027-03-15T09:00:01.987Z" ] } }, "required": [ "id", "webhookId", "eventId", "eventType", "status", "attempts", "responseStatus", "lastError", "createdAt", "deliveredAt" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "DeliveryId": { "schema": { "type": "string", "minLength": 1, "examples": [ "dlv_9f3e6b2a4c1d4a8eb7f51d2c8e0a6b49" ] }, "required": true, "name": "deliveryId", "in": "path" }, "WebhookId": { "schema": { "type": "string", "minLength": 1, "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Rotate Signing Secret (/docs/api-reference/webhooks/rotate-webhook-secret) Replaces the webhook's signing secret. Deliveries are signed with the new secret right away, so update your endpoint with it. `POST https://api.onepostly.com/v1/webhooks/{id}/rotate-secret` ```json { "paths": { "/v1/webhooks/{id}/rotate-secret": { "post": { "operationId": "rotateWebhookSecret", "tags": [ "Webhooks" ], "summary": "Rotate signing secret", "description": "Replaces the webhook's signing secret. Deliveries are signed with the new secret right away, so update your endpoint with it.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/WebhookId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "responses": { "200": { "description": "The webhook with its new secret. The secret is shown only in this response.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookWithSecret" }, "example": { "id": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "name": "Production", "url": "https://example.com/hooks/onepostly", "enabled": true, "events": [ "post.published", "post.failed", "account.expired", "account.revoked" ], "createdAt": "2027-03-14T16:20:00.000Z", "updatedAt": "2027-03-15T12:00:00.000Z", "secret": "Lw4nQ8xTb2Rk7pZc1vHs9mYd3fJe6gAu" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "description": "No webhook with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "$ref": "#/components/responses/ConflictReplayable" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WebhooksApi } from \"@onepostly/sdk\";\n\nconst webhooksApi = new WebhooksApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await webhooksApi.rotateWebhookSecret({\n id: \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.webhooks_api import WebhooksApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n webhooks_api = WebhooksApi(api_client)\n response = await webhooks_api.rotate_webhook_secret(\n \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58/rotate-secret\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "WebhookWithSecret": { "allOf": [ { "$ref": "#/components/schemas/Webhook" }, { "type": "object", "properties": { "secret": { "type": "string", "description": "Signing secret. It is shown only here; store it now.", "examples": [ "s7a9Kx2mQ8vB4nR6tY3wZ1pL5oN0uMf" ] } }, "required": [ "secret" ] } ] }, "Webhook": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "name": { "type": "string", "examples": [ "Post events" ] }, "url": { "type": "string", "format": "uri", "examples": [ "https://example.com/hooks/onepostly" ] }, "enabled": { "type": "boolean", "description": "false while the webhook is paused. A paused webhook receives no events.", "examples": [ true ] }, "events": { "type": "array", "items": { "type": "string" }, "description": "Event types the webhook receives, as you set them. [\"*\"] means every event type, including ones added later.", "examples": [ [ "post.published" ] ] }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "name", "url", "enabled", "events", "createdAt", "updatedAt" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "WebhookId": { "schema": { "type": "string", "minLength": 1, "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ConflictReplayable": { "description": "The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Send Test Event (/docs/api-reference/webhooks/test-webhook) Sends a webhook.test event to the webhook, whatever it subscribes to. Check its result in List Deliveries. `POST https://api.onepostly.com/v1/webhooks/{id}/test` ```json { "paths": { "/v1/webhooks/{id}/test": { "post": { "operationId": "testWebhook", "tags": [ "Webhooks" ], "summary": "Send test event", "description": "Sends a webhook.test event to the webhook, whatever it subscribes to. Check its result in List Deliveries.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/WebhookId" }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "responses": { "200": { "description": "Test event queued", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "sent": { "type": "boolean", "description": "false when the event could not be queued." } }, "required": [ "sent" ] }, "example": { "sent": true } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequiredReplayable" }, "403": { "$ref": "#/components/responses/ForbiddenReplayable" }, "404": { "description": "No webhook with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "$ref": "#/components/responses/ConflictReplayable" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WebhooksApi } from \"@onepostly/sdk\";\n\nconst webhooksApi = new WebhooksApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await webhooksApi.testWebhook({\n id: \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.webhooks_api import WebhooksApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n webhooks_api = WebhooksApi(api_client)\n response = await webhooks_api.test_webhook(\n \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X POST \"https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58/test\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\"" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] } }, "parameters": { "IdempotencyKey": { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "examples": [ "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d" ] }, "required": false, "description": "A unique key, such as a UUID, that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the first response instead of acting again. A 429 or 5xx response is not kept, so a retry with the same key runs again.", "name": "Idempotency-Key", "in": "header" }, "WebhookId": { "schema": { "type": "string", "minLength": 1, "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "IdempotentReplayed": { "description": "true when this response is the stored response of an earlier request with the same Idempotency-Key.", "schema": { "type": "string" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ConflictReplayable": { "description": "The Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED), or a request with it is still running (IDEMPOTENCY_KEY_IN_USE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ForbiddenReplayable": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequiredReplayable": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Idempotent-Replayed": { "$ref": "#/components/headers/IdempotentReplayed" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ``` # Update Webhook (/docs/api-reference/webhooks/update-webhook) Changes a webhook. Only the fields you send change. `PATCH https://api.onepostly.com/v1/webhooks/{id}` ```json { "paths": { "/v1/webhooks/{id}": { "patch": { "operationId": "updateWebhook", "tags": [ "Webhooks" ], "summary": "Update webhook", "description": "Changes a webhook. Only the fields you send change.", "security": [ { "Bearer": [] } ], "parameters": [ { "$ref": "#/components/parameters/WebhookId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateWebhookBody" } } } }, "responses": { "200": { "description": "Updated webhook", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Webhook" }, "example": { "id": "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58", "name": "Production", "url": "https://example.com/hooks/onepostly", "enabled": true, "events": [ "*" ], "createdAt": "2027-03-14T16:20:00.000Z", "updatedAt": "2027-03-15T12:30:00.000Z" } } } }, "400": { "description": "The request is invalid, for example when url is not a public HTTPS address (VALIDATION_ERROR)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "description": "This API key is read-only. Use a read-write key. The API key cannot use this part of the API (GROUP_DISABLED)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "No webhook with this id (NOT_FOUND)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/InternalError" } }, "x-codeSamples": [ { "lang": "typescript", "label": "TypeScript", "source": "import { Configuration, WebhooksApi } from \"@onepostly/sdk\";\n\nconst webhooksApi = new WebhooksApi(\n new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })\n);\n\nconst response = await webhooksApi.updateWebhook({\n id: \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n updateWebhookBody: {\n \"events\": [\n \"*\"\n ]\n },\n});\nconsole.log(response);" }, { "lang": "python", "label": "Python", "source": "import asyncio\nimport os\n\nfrom onepostly import ApiClient, Configuration\nfrom onepostly.api.webhooks_api import WebhooksApi\n\n\nasync def main() -> None:\n configuration = Configuration(access_token=os.environ[\"ONEPOSTLY_API_KEY\"])\n async with ApiClient(configuration) as api_client:\n webhooks_api = WebhooksApi(api_client)\n response = await webhooks_api.update_webhook(\n \"whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\",\n update_webhook_body={\n \"events\": [\n \"*\"\n ]\n },\n )\n print(response)\n\n\nasyncio.run(main())" }, { "lang": "bash", "label": "cURL", "source": "curl -X PATCH \"https://api.onepostly.com/v1/webhooks/whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58\" \\\n -H \"Authorization: Bearer $ONEPOSTLY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"events\": [\n \"*\"\n ]\n}'" } ] } } }, "components": { "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Human-readable message for display. Do not branch on it.", "examples": [ "Post not found." ] }, "code": { "$ref": "#/components/schemas/ErrorCode" }, "param": { "type": "string", "description": "Request field at fault, when applicable.", "examples": [ "accounts.0.accountId" ] }, "details": { "type": "object", "additionalProperties": {}, "description": "Additional structured context, when available.", "examples": [ { "accountId": "acc_1699f4157fb643f49d2ac447491f32a8" } ] }, "platform": { "$ref": "#/components/schemas/Platform", "description": "Upstream platform that rejected the request, when applicable." }, "requestId": { "type": "string", "description": "Id of this request, also sent as the Request-Id header. Quote it when you contact support.", "examples": [ "req_8f2a64c1d3b94e0f9a7c5e2b1d0f3a6c" ] } }, "required": [ "error", "code" ] }, "Platform": { "anyOf": [ { "type": "string", "enum": [ "x", "instagram", "facebook", "threads", "linkedin", "youtube", "tiktok", "pinterest", "bluesky" ] }, { "type": "string" } ], "description": "The platform id. New platforms can be added, so handle a value you do not know.", "examples": [ "instagram" ] }, "ErrorCode": { "anyOf": [ { "type": "string", "enum": [ "VALIDATION_ERROR", "INVALID_CURSOR", "UNAUTHORIZED", "FORBIDDEN", "GROUP_DISABLED", "NOT_FOUND", "IDEMPOTENCY_KEY_REUSED", "IDEMPOTENCY_KEY_IN_USE", "RATE_LIMITED", "QUOTA_EXCEEDED", "INTERNAL_SERVER_ERROR", "SERVICE_UNAVAILABLE", "PAYMENT_METHOD_REQUIRED", "PAYMENT_PAST_DUE", "INSUFFICIENT_WALLET", "USAGE_BILLING_REQUIRED", "USAGE_BILLING_FAILED", "ACCOUNT_NOT_FOUND", "CONNECTION_INACTIVE", "CONNECTION_BROKEN", "TOKEN_INVALID", "TOKEN_EXPIRED", "PERMISSION_DENIED", "ACCOUNT_RESTRICTED", "ACCOUNT_SUSPENDED", "AUTH_FAILED", "CONNECT_FAILED", "RECONNECT_MISMATCH", "BLUESKY_RECONNECT_APP_PASSWORD", "INVALID_REDIRECT_URL", "REDIRECT_URL_REQUIRED", "INVALID_CONNECT_SESSION", "FACEBOOK_PAGES_FAILED", "INSTAGRAM_ACCOUNTS_FAILED", "PAGE_NOT_FOUND", "PLATFORM_MAINTENANCE", "PROFILE_IN_USE", "PROFILE_NAME_TAKEN", "PROFILE_NOT_FOUND", "UNSUPPORTED_PLATFORM", "STATS_FAILED", "LIST_FAILED", "REVIEWS_FAILED", "PROFILE_FAILED", "CREATOR_INFO_FAILED", "BOARDS_FAILED", "BOARD_CREATE_FAILED", "SANDBOX_MISMATCH", "UNSUPPORTED_MEDIA_TYPE", "MEDIA_NOT_FOUND", "MEDIA_NOT_UPLOADED", "MEDIA_TYPE_MISMATCH", "MEDIA_TOO_LARGE", "MEDIA_UNFETCHABLE", "INVALID_MEDIA", "MEDIA_REQUIRED", "MEDIA_UPLOAD_FAILED", "MEDIA_PROCESSING_FAILED", "MEDIA_PROCESSING_TIMEOUT", "CONTAINER_FAILED", "URL_OWNERSHIP_UNVERIFIED", "REEL_UPLOAD_FAILED", "STORY_UPLOAD_FAILED", "PUBLISH_FAILED", "PUBLISH_INTERRUPTED", "PLATFORM_UNAVAILABLE", "POST_NOT_PUBLISHED", "TEXT_TOO_LONG", "TEXT_REQUIRED", "CAPTION_TOO_LONG", "INVALID_FIRST_COMMENT", "INVALID_AI_LABEL", "UNSUPPORTED_MEDIA_KIND", "UNSUPPORTED_FEATURE", "INVALID_MULTI_IMAGE", "DUPLICATE_CONTENT", "GEO_RESTRICTION_FAILED", "INVALID_LINK", "INVALID_QUOTE", "INVALID_REPLY", "INVALID_TOPIC_TAG", "INVALID_AUDIO", "INVALID_SPONSOR", "INVALID_TRIAL_REEL", "INVALID_CAROUSEL", "TEXT_FORMAT_UNSUPPORTED", "PRIVACY_LEVEL_REQUIRED", "INVALID_PRIVACY_LEVEL", "INTERACTION_DISABLED", "SPAM_RISK", "POSTING_LIMIT_REACHED", "CAPACITY_LIMITED", "UPLOAD_LIMIT_EXCEEDED", "NOT_EDITABLE", "POST_PUBLISHING", "NOT_DELETABLE", "DELETE_FAILED", "DELETE_PERMISSION", "THREAD_DELETE_PARTIAL", "MEDIA_DELETE_UNSUPPORTED", "INVALID_EXTERNAL_ID", "NOT_PUBLISHED", "ACCOUNT_REQUIRED", "AMBIGUOUS_TARGET", "POST_ACCOUNT_MISMATCH", "TARGET_SYNC_FAILED", "MISSING_EXTERNAL_ID", "NOT_A_COMMENT", "COMMENT_CREATE_FAILED", "COMMENT_DELETE_FAILED", "COMMENT_HIDE_FAILED", "COMMENT_LIKE_FAILED", "COMMENT_UNLIKE_FAILED", "PRIVATE_REPLY_FAILED", "COMMENTS_PERMISSION", "COMMENTS_UNSUPPORTED", "UNSUPPORTED_MEDIA", "COMMENTS_FAILED", "INVALID_PARENT", "INVALID_COMMENT_ID", "RESOLVE_FAILED", "ENGAGEMENT_FAILED", "ENGAGEMENT_PERMISSION", "LIKE_FAILED", "UNLIKE_FAILED", "BOOKMARK_FAILED", "UNBOOKMARK_FAILED", "REPOST_FAILED", "UNREPOST_FAILED", "REPOST_PERMISSION", "UNREPOST_PERMISSION", "UNREPOST_REQUIRES_REPOST_ID", "REPOSTS_UNSUPPORTED", "REPOSTS_UNAUTHORIZED", "REPOSTS_FAILED", "READ_FAILED", "SYNC_FAILED", "CONVO_NOT_FOUND", "RECIPIENT_NOT_FOUND", "RECIPIENT_UNREACHABLE", "MESSAGE_WINDOW_EXPIRED", "CONVO_LOCKED", "INBOX_PERMISSION", "INBOX_FAILED", "INVALID_ATTACHMENT", "ATTACHMENT_UNSUPPORTED", "TEMPLATE_UNSUPPORTED", "INVALID_TEMPLATE", "LIMIT_REACHED", "CONFLICT", "INVALID_RANGE", "TIMELINE_UNSUPPORTED", "ANALYTICS_PERMISSION", "ANALYTICS_FAILED", "ANALYTICS_PENDING", "POST_NOT_FOUND", "VIDEO_ID_PENDING", "VIDEO_NOT_FOUND", "PRIVACY_RESTRICTED", "CREATE_FAILED", "DELIVERY_IN_PROGRESS" ], "x-enum-descriptions": [ "A field is missing or invalid, or the platform rejected a parameter.", "The cursor is not a nextCursor of this list.", "The API key is missing, invalid or deleted.", "A read-only key sent a write request, a key limited to some profiles went outside them, or the resource belongs to another workspace.", "The API key cannot use this part of the API.", "The resource does not exist in this workspace, or the id has another prefix.", "The Idempotency-Key was already used for a different request.", "A request with this Idempotency-Key is still running.", "A rate limit was reached, or the platform slowed down the account.", "The platform is at capacity for this action.", "An unexpected error. Try again later.", "The service is temporarily unavailable. Try again later.", "The workspace has 3 or more accounts and no payment method.", "A payment failed and the invoice is unpaid.", "The wallet cannot pay for this X action.", "Connecting another account needs a payment method.", "Billing for the new account could not be set up, so it was not connected.", "The account does not exist in this workspace.", "The account is disconnected or its access was revoked.", "The Instagram account connected with Facebook Login has no linked Page.", "The platform revoked or rejected the account's access. Reconnect the account.", "The platform says the account's access expired.", "The account did not grant a required permission, or the platform refused the action.", "The platform restricted the account.", "The Bluesky account was taken down, suspended or deactivated.", "Bluesky rejected the handle or App Password.", "The account could not be connected.", "A reconnect used a different account than the original.", "A Bluesky reconnect needs identifier and appPassword.", "redirectUrl is not a valid HTTPS URL.", "The request needs a redirectUrl.", "The connect session is malformed, was changed, or has expired.", "The user's Facebook Pages could not be listed.", "The linked Instagram accounts could not be listed.", "The picked Facebook Page is not available to this user.", "New connections to this platform are paused.", "An API key is limited to the profile.", "A profile with this name exists, or the name is reserved.", "The profile does not exist.", "The action is not available on this account's platform.", "The platform did not return account stats.", "The platform did not return the account's media or posts.", "Facebook did not return the Page reviews.", "Facebook did not read or update the Messenger profile.", "TikTok creator info could not be loaded.", "Pinterest boards could not be listed.", "Pinterest did not create the board.", "The Pinterest account cannot publish in the current Pinterest environment.", "The file type is not supported.", "A media id is not a media item in this workspace.", "The file was never uploaded, or the upload expired.", "The uploaded file's type is not the declared contentType.", "The file is over the size limit for its type.", "The media URL could not be downloaded.", "The platform rejected the media because of its format, count, size or kind.", "A media post has no media.", "The platform rejected or failed the media upload.", "X could not process the media.", "The platform did not finish processing the media in time.", "Instagram or Threads could not process the media.", "TikTok does not accept media from the URL's domain.", "Facebook did not accept the reel upload.", "Facebook did not accept the story upload.", "The platform rejected the post without a more specific reason.", "The outcome is unknown, and the post may be live.", "The platform is not accepting requests right now, had an outage or did not respond.", "quotePostId or replyToPostId names a post that is not live.", "The text is over the platform or account limit.", "A text post or message has no text.", "The Instagram caption is over 2,200 characters.", "The Instagram firstComment is over 2,200 characters.", "Instagram isAiGenerated was sent on a story.", "The platform cannot publish this mediaKind.", "A thread, quote or reply was sent to a platform that does not have them.", "The number of images is outside the platform's range.", "X rejected the text as a duplicate.", "X rejected the geoRestriction list.", "The Bluesky link is not a valid URL.", "The Bluesky post to quote is invalid or could not be found.", "The Bluesky post to reply to is invalid or could not be found.", "The Threads topicTag is too long or has a character Threads does not accept.", "Instagram audioId was used on a post or account that cannot take it.", "An Instagram sponsor could not be found, or the account cannot take the paid partnership label.", "An Instagram trial reel is not a single video, or has sponsors.", "Facebook carouselCards does not match the post's images.", "Facebook textFormatPresetId was sent on a post that is not text-only.", "The TikTok privacyLevel is missing or invalid.", "The TikTok privacyLevel is not one the creator allows.", "A TikTok interaction the creator turned off was set to true.", "TikTok flagged the post as a spam risk.", "TikTok says the account posted too often.", "TikTok is not accepting more direct posts right now.", "The YouTube channel reached its upload limit.", "The post is not scheduled, or was made outside Onepostly.", "The post is being published right now.", "There is nothing on the platform to delete.", "The platform did not delete the post.", "The account cannot delete this post.", "The first post was deleted, but some posts of its thread were not.", "Instagram accounts connected with Instagram Login cannot delete media.", "The Bluesky post id is not an at:// URI.", "The post is not published yet.", "A platform post id was sent without accountId.", "The post has several published accounts. Pass accountId to pick one.", "The post belongs to another account.", "The post could not be loaded from the platform.", "The post or comment has no usable platform id.", "The comment id points to a post, not a comment.", "The platform did not post the comment or reply.", "The platform did not delete the comment.", "The platform did not hide or unhide the comment.", "Facebook did not like the comment.", "Facebook did not remove the like.", "The private reply was not sent.", "The account cannot read or change comments on this post.", "Comments cannot be read for this post.", "The post is a story, which has no comments.", "The comments could not be read.", "The Bluesky comment to reply to has an invalid id.", "The Bluesky comment id is invalid.", "Bluesky could not find the post or the comment.", "The like or bookmark failed.", "The account is missing permission for likes or bookmarks.", "The platform did not like the post.", "The platform did not remove the like.", "The platform did not bookmark the post.", "The platform did not remove the bookmark.", "The platform did not repost the post.", "The platform did not remove the repost.", "The account cannot repost.", "The account cannot remove the repost.", "The Threads repost was not made through Onepostly.", "Reposts cannot be read for this post.", "X rejected the account's access while reading reposts.", "The reposts could not be read.", "The platform list could not be read.", "The account's posts could not be loaded.", "The conversation does not exist.", "The recipient does not exist.", "The recipient does not accept messages from this account.", "The 24-hour messaging window has closed.", "The Bluesky conversation is locked.", "The account is missing messaging permission.", "The platform did not complete the inbox request.", "attachmentUrl is not an HTTPS URL.", "Attachments only work on Instagram and Facebook.", "Quick replies, buttons and cards only work on Instagram and Facebook.", "A button is invalid, or an attachment was combined with buttons or cards.", "The account already has the most automations it can have.", "The automations changed while the request ran.", "since is not earlier than until, or the range is too long.", "X posts have no daily timeline.", "The account is missing the insights permission.", "The platform did not return metrics.", "The platform has no metrics yet.", "The post was deleted from the platform, or the account can no longer see it.", "The TikTok video is not public yet.", "The platform has no metrics for the video yet, or it was removed.", "TikTok only reports metrics for public posts.", "The webhook endpoint could not be created. Try again.", "The delivery is still being attempted." ] }, { "type": "string" } ], "description": "Stable machine-readable error code. Branch on this value. New codes can be added, so handle a code you do not know by its HTTP status. Every code is listed at https://onepostly.com/docs/error-handling#error-codes.", "examples": [ "VALIDATION_ERROR" ] }, "Webhook": { "type": "object", "properties": { "id": { "type": "string", "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "name": { "type": "string", "examples": [ "Post events" ] }, "url": { "type": "string", "format": "uri", "examples": [ "https://example.com/hooks/onepostly" ] }, "enabled": { "type": "boolean", "description": "false while the webhook is paused. A paused webhook receives no events.", "examples": [ true ] }, "events": { "type": "array", "items": { "type": "string" }, "description": "Event types the webhook receives, as you set them. [\"*\"] means every event type, including ones added later.", "examples": [ [ "post.published" ] ] }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "name", "url", "enabled", "events", "createdAt", "updatedAt" ] }, "UpdateWebhookBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 120 }, "url": { "type": "string", "maxLength": 2048, "format": "uri", "description": "HTTPS URL that receives the events.", "examples": [ "https://example.com/hooks/onepostly" ] }, "events": { "type": "array", "items": { "type": "string", "enum": [ "*", "post.scheduled", "post.published", "post.failed", "post.cancelled", "post.deleted", "post.updated", "post.created", "comment.created", "comment.deleted", "comment.received", "message.received", "message.sent", "message.delivered", "message.read", "message.deleted", "message.reaction", "message.postback", "review.received", "engagement.liked", "engagement.unliked", "engagement.bookmarked", "engagement.unbookmarked", "engagement.reposted", "engagement.unreposted", "account.connected", "account.disconnected", "account.expiring", "account.expired", "account.revoked", "webhook.test" ] }, "minItems": 1, "maxItems": 30, "description": "Event types to receive, from List Event Types. [\"*\"] receives every event type, including ones added later. \"*\" must be the only item, or the request returns VALIDATION_ERROR.", "examples": [ [ "post.published", "post.failed" ], [ "*" ] ] }, "enabled": { "type": "boolean", "description": "false pauses the webhook, true resumes it." } } } }, "parameters": { "WebhookId": { "schema": { "type": "string", "minLength": 1, "examples": [ "whk_e5c7a3f18b2d4e69a04c3f9d1b7e2c58" ] }, "required": true, "name": "id", "in": "path" } }, "headers": { "RateLimitReset": { "description": "Unix time, in seconds, when the window frees its next request.", "schema": { "type": "integer" } }, "RateLimitRemaining": { "description": "Requests left in the current window.", "schema": { "type": "integer" } }, "RateLimitLimit": { "description": "Requests allowed in the current window.", "schema": { "type": "integer" } }, "RequestId": { "description": "Id of this request. Quote it when you contact support.", "schema": { "type": "string" } }, "RetryAfter": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } } }, "responses": { "InternalError": { "description": "An unexpected error. Try again later. If it keeps happening, contact support with the requestId", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "RateLimited": { "description": "A rate limit was reached, or the platform is throttling the account. When Retry-After is sent, wait that many seconds, then try again.", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "PaymentRequired": { "description": "The workspace is blocked on billing until a payment method is added (PAYMENT_METHOD_REQUIRED) or the unpaid invoice is paid (PAYMENT_PAST_DUE)", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "The API key is missing or invalid", "headers": { "Request-Id": { "$ref": "#/components/headers/RequestId" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } ```