Guides · Updated

X API rate limits for posting, explained

A 429 Too Many Requests from the X API means a rate limit or usage cap was reached. For posting, X's current rate-limit table lists 100 requests per 15 minutes per user and 10,000 per 24 hours per app for POST /2/tweets. Those are request windows, not a monthly posting subscription or a promise that every app can publish that many posts.

Checked on October 26, 2026 against X's own rate-limit reference, manage-posts guide, create-post reference, response codes and pricing documentation. The pages disagree on one posting limit; that difference is called out below. Check your app's Developer Console and actual response headers before planning a burst.

Pay-per-use, Enterprise and the old plan names

X's current pricing page describes pay-per-use, with no required subscription: credits pay for usage. Its current rate-limit reference publishes one endpoint table, not separate Free, Basic and Pro posting tables. Enterprise customers have custom rate limits.

If you found an old Twitter API Free, Basic or Pro quota, don't treat it as today's pay-per-use allowance. These current pages don't establish a current posting quota for each old tier or the terms of a particular legacy account. Check the plan and limits shown for that app in the Console. An X Premium account subscription is not an API request allowance.

Three different constraints can stop a post:

For costs and credit behavior, use X API pricing, explained. The numbers below are request limits, not prices or monthly plan entitlements.

Posting limits: per user and per app

These are the figures in X's rate-limit reference on the checked date:

Endpoint Per user Per app
POST /2/tweets: a post, reply or thread part 100 per 15 minutes 10,000 per 24 hours
DELETE /2/tweets/:id 50 per 15 minutes Not listed

Per user means the account represented by the user token. The manage-posts guide says its user allowance applies across any developer App: two tools posting for the same account don't each get a fresh user allowance. Per app is the app-level column, not 10,000 for each connected person. A new access token is not a new person or a new allowance.

There is an authentication wrinkle in X's documentation: the general rate-limit page labels per-app limits as applying to app-only bearer tokens, but the create-post reference requires user authorization. An app-only bearer token cannot publish a post. The per-app column is not another way to authenticate; confirm the counters that apply to your app in the Console rather than assuming one response header describes every applicable allowance.

Why another X page says 200, not 100

The manage-posts guide still states 200 posting requests per 15 minutes per user, plus 300 requests per 3 hours combining post creation and reposts. The central rate-limit table instead says 100 per 15 minutes for creation. Neither page explains that discrepancy or gives a plan mapping that resolves it.

Don't build around the larger number. Use 100 per 15 minutes as the conservative published reference, account for the separately documented 300-per-three-hour allowance, and monitor the actual counters. Staying under one window doesn't prove the others have room. Enterprise's custom terms may differ; this table is not its contract.

Threads and media have more than one request

A five-part thread needs five POST /2/tweets requests: the root and four replies. It is not one write because your UI shows one review item. A retry should continue from the first unsent part, not recreate the root.

Media endpoints have their own counters. X's table lists:

Endpoint Per user Per app
POST /2/media/upload: one-step upload 500 per 15 minutes 50,000 per 24 hours
POST /2/media/upload/initialize 1,875 per 15 minutes 180,000 per 24 hours
POST /2/media/upload/:id/append 1,875 per 15 minutes 180,000 per 24 hours
POST /2/media/upload/:id/finalize 1,875 per 15 minutes 180,000 per 24 hours
GET /2/media/upload: processing status 1,000 per 15 minutes 100,000 per 24 hours
POST /2/media/metadata: alt text 500 per 15 minutes 50,000 per 24 hours

Each appended segment is a request to the append endpoint; status polling consumes the status endpoint's allowance. A successful upload doesn't prove there is room to create the post. For the upload sequence and payloads, see threads, polls and media with the X API v2.

Reading a Twitter API 429 and its reset headers

X's response-code reference describes 429 as rate limit or usage cap exceeded, with problem types rate-limit-exceeded and usage-capped. Its rate-limit page also shows an error body with code 88 and message Rate limit exceeded. Don't require that one body shape to recognize every 429; read the HTTP status and the returned problem details.

Response header What it tells you
x-rate-limit-limit Maximum requests in the reported window
x-rate-limit-remaining Requests left in that window
x-rate-limit-reset Unix timestamp, in seconds, when that window resets

Read these headers on successful responses too. When remaining reaches zero, wait for that window's reset instead of sending another write just to discover it is exhausted. The reset is an absolute time, not a number of seconds to sleep. In JavaScript, convert it to milliseconds before comparing it with Date.now().

If your clock is 90 seconds before the reported reset, wait at least those 90 seconds; don't retry once a second. That is an illustrative calculation, not a fixed X retry delay. A reset for one reported counter is not proof that a longer user, app or usage allowance has reset too.

How to back off without duplicating a post

X recommends waiting until x-rate-limit-reset and using exponential backoff if needed. In your own integration:

  1. Keep the rejected work queued. Record the status, endpoint, account, reset and problem type, without logging credentials or private post content. Coordinate workers using the same applicable counter, rather than having every worker retry independently.
  2. Honor a valid future reset first. Wait until it has passed. Add a little randomized delay so a whole queue doesn't wake at the exact same instant; jitter should never move the retry before the reset.
  3. If the reset is missing, invalid or already past and 429 continues, back off progressively. Increase the delay between attempts exponentially, with jitter, instead of immediately looping. Re-read the headers on each response. These are integration recommendations, not a claim that X specifies one universal delay sequence.
  4. Distinguish a usage cap from a short-window limit. For usage-capped, inspect the Console's usage allowance and reset period. Repeating a request after a 15-minute boundary won't fix a different exhausted allowance. For credits or spending, follow the pricing guide, not a rate-limit retry loop.
  5. Retry only the unsent operation. Preserve successful post IDs and a thread's reply chain. A timeout or 5xx is not the same as a definite 429 refusal: if X may have accepted a write before the connection failed, reconcile the outcome before sending it again. Don't rotate accounts, apps or tokens to get around a limit.

Spread legitimate queued work through the window and use the remaining count as feedback. Don't assume windows reset at midnight or on a fixed wall-clock quarter hour; use the timestamp X returns. Reconnecting an account fixes some sign-in failures, not exhausted rate counters.

Posting through Flaghand

The backoff steps above are advice for an integration you build, not a claim that Flaghand implements that exact retry policy. Flaghand's current retry and held-job behavior, plus the separate 401, 403, credit and media failures, are in X API posting errors, explained. Waiting for a reset doesn't approve a new post or automatically restart a held job.

In Flaghand, an agent drafts, checks and requests approval; only the owner can approve the exact plan with a passkey. No API-token scope lets an agent approve, schedule or post. Get access to Flaghand.