X API guide
X API guide: posting with POST /2/tweets, media upload, pricing and limits
X's API v2 creates a post with POST /2/tweets and a user-context token that carries the tweet.read, tweet.write and users.read scopes; photos and videos go up first through the chunked media upload endpoints, under media.write. Since 6 February 2026 X sells API access pay-per-use with credits bought in its Developer Console: Post: Create costs USD 0.015 per request, or USD 0.200 per request when the post has a URL. This guide sums up X's own developer pages, read on 15 October 2026.
- Sources read on
- Checked on
What the posting endpoint does
POST https://api.x.com/2/tweets creates a Post. The JSON body is strict: X's schema sets additionalProperties to false, so a field X does not know is rejected instead of ignored. The text field is "Required unless media is provided." [X1]
A successful call answers 201 with data.id and data.text, plus edit_history_post_ids. Keep data.id: it is the only handle on the new Post. [X1]
The same endpoint edits a recent Post through edit_options.previous_post_id. X added this on 3 October 2025; it needs X Premium, works only on your own Post, and only on a Post created within the last hour. [X1, X5]
Getting access in 2026
A review step and a wait time: not listed. X's getting-access page describes neither. X recommends separate apps for development, staging and production. [X6, X7]
The current setup dates from 6 February 2026, when X "officially launched X API Pay-Per-Use pricing" together with a new Developer Console at console.x.com, the XDK (first-party Python and TypeScript SDKs), an interactive Playground for testing and an MCP server for AI models. X's changelog adds that Basic and Pro plans remain available and existing subscribers can opt in to pay-per-use, and that Public Utility Apps continue to receive free scaled access. The pricing page itself lists only pay-per-usage. [X5, X2]
- Go to console.x.com and sign in with your X account. [X6]
- Accept the Developer Agreement and Policy, then complete a profile with basic information about how you will use the API. [X6]
- Click New App and give it a name, a description and a use case. [X6]
- Save the credentials straight away. In X's words, "Credentials are only displayed once". [X6]
X API pricing: pay-per-use
X states the model plainly: "The X API uses pay-per-usage pricing with no subscriptions." You buy credits upfront in the Developer Console, each request deducts from them, and there are "No contracts, subscriptions, or minimum spend." [X2]
| X's line item | Price in US dollars, in X's units |
|---|---|
| Post: Create | USD 0.015 per request |
| Post: Create (with URL) | USD 0.200 per request |
| Post: Create (summoned) | USD 0.010 per request |
| Media Metadata | USD 0.005 per request |
| Posts: Read | USD 0.005 per resource |
| User: Read | USD 0.010 per resource |
| Owned Reads (your own posts, bookmarks, followers) | USD 0.001 per resource |
Sources: [X2]
- Reads are charged per resource returned, and X deduplicates resources within a 24-hour UTC day, which it calls a soft guarantee. [X2]
- Pay-per-usage plans are capped at 3 million Post reads per monthly billing cycle; more than that needs an Enterprise plan. [X2, X3]
- When the credits run out, the balance can go slightly negative; after that, requests are blocked until you add credits to cover it. Spending limits can be set in the Developer Console. [X2, X3]
- A price for media upload: not listed. The only media line on the price list is Media Metadata. [X2]
- One-time credits, which X marks as currently rolling out: USD 20 when an account saves its first eligible card, and a credit matching the first automatic recharge, up to USD 50. Both expire 3 months after they are granted. [X4]
- A free tier: not listed on the pricing page. The 6 February 2026 changelog entry says recently active Legacy Free tier users received a one-time USD 10 voucher. [X2, X5]
Authentication and scopes
- POST /2/tweets lists only user-context authentication: an OAuth 2.0 user token with tweet.read, tweet.write and users.read, or the user token X's reference lists as UserToken. An app-only bearer token is not among them. [X1]
- Media upload and alt text need media.write, which X describes as "Upload media, such as photos and videos, on your behalf." [X11, X12]
- Sign-in: X's OAuth 2.0 flow uses PKCE. Send the user to https://x.com/i/oauth2/authorize and exchange the code at https://api.x.com/2/oauth2/token. code_challenge_method is S256 or plain, and the authorization code is valid for 30 seconds. [X8]
- Tokens: the access token stays valid for two hours unless you asked for the offline.access scope, which gets you a refresh token. Whether refresh tokens rotate: not listed. [X8]
- Client types: web apps and automated apps or bots are confidential clients; native apps and single-page apps are public clients. [X8]
- Callback URLs must match exactly, trailing slash included, and an app can have at most 10. [X7]
- Changing an app's permissions makes its users authorize the app again. The OAuth 1.0a levels are Read only; Read and write; and Read, write, and DMs. [X7]
- Since 21 September 2026, an app can exchange stored OAuth 1.0a user tokens for OAuth 2.0 tokens without a consent screen; offline.access is always included. [X5]
Posting with a photo or video, step by step
- Start the upload: POST /2/media/upload/initialize with media_type, total_bytes and media_category. The answer carries the media id, a media_key and expires_after_secs. [X10, X11]
- Send the file: POST /2/media/upload/{id}/append once per chunk, with segment_index counting from 0. X says: "Keep each segment at or below 5 MB (the server maximum is 8 MB)." [X10]
- Close the upload: POST /2/media/upload/{id}/finalize. [X10]
- If finalize returns processing_info, poll GET /2/media/upload?command=STATUS&media_id={id}, waiting check_after_secs between calls, until the state moves from pending and in_progress to succeeded or failed. X's initialize and finalize examples show expires_after_secs as 86400 without explaining it further. [X10]
- Optional alt text: POST /2/media/metadata with the media id and metadata.alt_text.text, up to 1,000 characters. [X12]
- Create the Post: POST /2/tweets with text and media.media_ids, which takes 1 to 4 ids, then read data.id from the 201. [X1]
curl -X POST 'https://api.x.com/2/tweets' \
-H 'Authorization: Bearer {user_access_token}' \
-H 'Content-Type: application/json' \
-d '{
"text": "Our new studio is open",
"media": { "media_ids": ["{media_id}"] }
}'Post options in the request body
- reply_settings, "Who can reply to this tweet.": following, mentionedUsers, subscribers or verified. [X1]
- community_id posts to a Community. Since 28 July 2025, share_with_followers with a community_id also shows the Community post on your followers' timelines. Whether the account must be a member of the Community: not listed. [X1, X5]
- made_with_ai: "Disclose that the tweet contains AI-generated media." paid_partnership: "Disclose that the tweet is a paid partnership", added on 3 June 2026. [X1, X5]
- poll: 2 to 4 options of 1 to 25 characters each, with duration_minutes from 5 to 10,080. [X1]
- reply.in_reply_to_tweet_id makes a reply. quote_tweet_id makes a quote post, and X says it requires an Enterprise plan and is not available on self-serve (pay-per-use) tiers. [X1]
- Also accepted: media.tagged_user_ids (at most 10), nullcast, geo.place_id, for_super_followers_only and card_uri. [X1]
Media specs
- Image types: JPG, PNG, GIF and WEBP. media_type values include video/mp4, video/webm, video/quicktime, image/jpeg, image/png and image/webp, and total_bytes can be at most 17,179,869,184. [X9, X11]
- A video must be at least 0.5 seconds long. A Post holds up to 4 photos, 1 animated GIF or 1 video. [X9]
- Since 1 September 2026 the caps follow the posting user's Premium or verified status, not your API plan. [X5]
- X says "Upload and posting are separately enforced": a file can upload and still be refused with 403 when you attach it to a Post. [X9]
Text and character counting
- X's rule: "Posts on X can contain up to 280 characters." [X15]
- Every URL is wrapped by t.co and counts as 23 characters, whatever its real length. Emoji and CJK characters count as 2. Media attached through official clients counts as 0. [X15]
- Longer posts for Premium accounts: not listed on X's counting page. [X15]
Rate limits
| Endpoint | Per user | Per app |
|---|---|---|
| POST /2/tweets | 100 per 15 minutes | 10,000 per 24 hours |
| DELETE /2/tweets/:id | 50 per 15 minutes | Not listed |
| POST /2/media/upload | 500 per 15 minutes | 50,000 per 24 hours |
| POST /2/media/upload/initialize, append, finalize | 1,875 per 15 minutes | 180,000 per 24 hours |
| GET /2/media/upload | 1,000 per 15 minutes | 100,000 per 24 hours |
| POST /2/media/metadata | 500 per 15 minutes | 50,000 per 24 hours |
Sources: [X13]
Errors X returns
| HTTP | What X says it means |
|---|---|
| 400 | Invalid JSON, malformed query, missing required parameters |
| 401 | Invalid or missing authentication credentials |
| 403 | Valid auth but no permission for this resource or action |
| 429 | Rate limit or usage cap exceeded |
| 500 | Wait and retry; check status page |
| 503 | X is overloaded; wait and retry |
Sources: [X14]
- Problem types in the error body include client-forbidden ("App not enrolled or lacks required access"), usage-capped ("Usage cap exceeded"), rate-limit-exceeded, invalid-request and not-authorized-for-resource. [X14]
- A video longer than the account may post gets 403 "This user is not allowed to post a video longer than 20 minutes." [X1]
- Duplicate posts: the X Developer Policy says "Never post identical or substantially similar content across multiple accounts". [X16]
What changed in 2025 and 2026
X's changelog dates every change; its newest entry when we read it was 2 October 2026. [X5]
- 16 January 2025: new API v2 media upload endpoints. 30 April 2025: dedicated endpoints for chunked upload. 28 July 2025: share_with_followers for Community posts. 22 August 2025: like and follow writes removed from the Free tier. [X5]
- 3 October 2025: editing recent Posts. 20 October 2025: a pay-per-use pilot. 6 February 2026: pay-per-use launched with the new Developer Console. [X5]
- 23 February 2026: on self-serve tiers, replies through POST /2/tweets are only permitted when the original Post's author summoned the replier with an @mention or a quote, and further restrictions apply to programmatic @mentions and quotes. How this treats replies to your own posts: not listed. [X5]
- 16 April 2026: new prices, and Following, Likes and Quote-Posts removed from all self-serve tiers. 3 June 2026: paid_partnership. [X5]
- 1 September 2026: upload and posting caps follow the user's Premium status. 21 September 2026: OAuth 1.0a to 2.0 token exchange. 2 October 2026: free-credit incentives. [X5]
Gotchas developers hit
- Calling POST /2/tweets with an app-only bearer token: the endpoint lists only user-context authentication. [X1]
- Forgetting offline.access: there is no refresh token, so the access token stops working after two hours. And the authorization code itself lasts only 30 seconds. [X8]
- A callback URL that differs by one character, a trailing slash included. [X7]
- Sending the old command-style INIT, APPEND and FINALIZE calls to /2/media/upload instead of the dedicated endpoints. [X10]
- An extra field in the body: additionalProperties is false, so X rejects it. [X1]
- Assuming your API plan sets the video cap: the posting account's Premium or verified status does. [X9, X5]
- Replying or quoting from a self-serve tier: replies need a summons, and quote_tweet_id needs Enterprise. [X1, X5]
- Forgetting that a URL in the text turns a USD 0.015 request into a USD 0.200 one. [X2]
Posting to X through Status 200 Uploads
Status 200 Uploads posts to X through its own X app: you sign in on X itself and never create a developer app or go through the access steps above. The facts below are the ones our X page shows, as checked on that page's own date.
- What you can post
- Text only, text with one image, text with up to 4 images, or text with one video.
- The X add-on
- X needs the X add-on: $9 a month on any plan, Free included, for 200 X posts per billing month, at most 20 of them with a link. X posts do not count toward the plan's own posts. Pricing
- Largest video
- 5 GB per file. File limits of every network
- Largest image
- 5 MB per image.
- Text
- Up to 280 characters, counted the way X counts them: every link counts as 23, an emoji as 2.
- Scheduling
- Schedule a post up to 365 days ahead, or send it now.
- Your own X developer account
- Not needed: posts go out through our X app, so you never pay for or apply for X API access yourself.
Settings you can choose: Who can reply.
X API questions
X sells pay-per-use credits in its Developer Console, with no subscription. Post: Create is USD 0.015 per request, or USD 0.200 per request when the post has a URL, and Posts: Read is USD 0.005 per resource. Post reads are capped at 3 million per monthly billing cycle.
X's pricing page describes none. New accounts can get one-time credits that X marks as rolling out: USD 20 for saving a first eligible card and up to USD 50 matching the first automatic recharge, both expiring after 3 months.
Send POST https://api.x.com/2/tweets with a user-context token that carries tweet.read, tweet.write and users.read. A 201 answer returns data.id, the new Post's id.
Call /2/media/upload/initialize, send chunks of at most 5 MB to /2/media/upload/{id}/append, call finalize, poll the status until it is succeeded, then attach the media id in media.media_ids. The scope is media.write.
X enforces upload and posting separately. Videos are capped at 20 minutes and 8 GB for a default account, or 125 minutes and 16 GB for a Premium or verified one, and since 1 September 2026 the posting account's status decides the cap.
100 requests per 15 minutes per user and 10,000 per 24 hours per app. Over the limit X answers 429 with error code 88.
Since 23 February 2026, self-serve tiers may reply only when the original Post's author summoned you. Since 16 April 2026 quote posts are off the self-serve tiers, and quote_tweet_id needs an Enterprise plan.
Two hours. Ask for the offline.access scope to get a refresh token; the authorization code itself is valid for 30 seconds.
X's own pages
Sources read on 15 October 2026.
- X1Create Posts (POST /2/tweets) (no date shown)
- X2Pay-per-usage pricing and credits (no date shown)
- X3Usage and Billing (no date shown)
- X4Free credits (no date shown)
- X5X API changelog (no date shown)
- X6Getting access (no date shown)
- X7Apps (no date shown)
- X8OAuth 2.0 Authorization Code Flow with PKCE (no date shown)
- X9Media upload introduction (no date shown)
- X10Chunked media upload quickstart (no date shown)
- X11Initialize media upload (no date shown)
- X12Create Media metadata (no date shown)
- X13Rate limits (no date shown)
- X14Response codes and errors (no date shown)
- X15Counting characters (no date shown)
- X16X Developer Policy (no date shown)
Post to X without building it yourself
X needs the X add-on: $9 a month on any plan, Free included, for 200 X posts per billing month, at most 20 of them with a link. X posts do not count toward the plan's own posts. This page was checked on 26 October 2026.