API Basics

Rate Limits

Request limits, rate limit headers, and how many posts and actions each account can take.

The API limits workspace requests, and each account's posts and actions.

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.

WorkspaceRequests per minuteAnalytics per second
Free, up to 2 accounts606
Paid, 3 or more accounts60010
  • 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

Every authenticated response has these headers.

HeaderDescription
X-RateLimit-LimitThe window's limit
X-RateLimit-RemainingRequests left in the window
X-RateLimit-ResetUnix seconds when the oldest request stops counting
Retry-AfterSeconds to wait, only on a 429

Handle 429 Responses

Over the limit, you get 429 RATE_LIMITED with a Retry-After header.

{
  "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.

import { Configuration, PostsApi, ResponseError } from "@onepostly/sdk";

const postsApi = new PostsApi(
  new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);

async function withRetry<T>(
  call: () => Promise<T>,
  { maxAttempts = 3, maxWaitSeconds = 60 } = {}
): Promise<T> {
  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);

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.

PlatformPosts per day
X50
Instagram100
Facebook100
Threads250
LinkedIn50
YouTube50
TikTok50
Pinterest25
Bluesky50
  • 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.
PostOver the limitWhat to do
Published now429 RATE_LIMITED. Nothing is created, for any accountWait for Retry-After, or drop that account
ScheduledEnds failed with RATE_LIMITED. Other accounts are not affectedCreate a new post later

A scheduled post's error.message says how long to wait.

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.

RequestOver the limit
A comment, like, repost, bookmark, delete or message429 QUOTA_EXCEEDED, with no Retry-After
A postEnds 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

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.

CodeMeaningWhat to do
RATE_LIMITEDThe platform slowed the accountWait, then post again
QUOTA_EXCEEDEDAn action limit, or the platform is at capacityTry again after the time in the message
POSTING_LIMIT_REACHEDTikTok says the account posted too oftenWait before posting again
CAPACITY_LIMITEDTikTok is not taking more direct posts nowTry again in a few hours
UPLOAD_LIMIT_EXCEEDEDThe YouTube channel hit its upload limitWait for YouTube's reset

Other codes are in Error Codes.

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 instead of polling post status.
  • Spread one account's scheduled posts over the day to stay under the hourly limit.