Twitter API v2: Create a Tweet
The exact X/Twitter API v2 call to create a post.
Call POST /2/tweets with a JSON body containing a text field, authenticated via OAuth 1.0a user context or an OAuth 2.0 user access token with the tweet.write scope. A standard post costs $0.015 under X’s pay-per-use pricing ($0.200 if the text contains a URL); media is uploaded separately and referenced by media_ids.
The exact call is POST /2/tweets. Everything else on this page — auth, cost, response shape, and media attachment — is what makes that one line actually work in production. If you'd rather not hold X developer credentials at all, the same result is one PostGate call instead.
The exact endpoint
text field, authenticated as the posting user via OAuth 1.0a user context or an OAuth 2.0 user access token with the tweet.write scope (and users.read if you also need to resolve the author).curl -X POST https://api.x.com/2/tweets \
-H "Authorization: OAuth oauth_consumer_key=\"...\",oauth_token=\"...\",oauth_signature=\"...\",..." \
-H "Content-Type: application/json" \
-d '{ "text": "Launch day. 🚀" }'The response shape
{
"data": {
"id": "1987650001234567890",
"text": "Launch day. 🚀"
}
}What does this specific call cost?
How do you attach media to the same call?
media_id values are referenced by ID in the create-post call.curl -X POST https://api.x.com/2/tweets \
-H "Authorization: OAuth oauth_consumer_key=\"...\",oauth_token=\"...\",oauth_signature=\"...\",..." \
-H "Content-Type: application/json" \
-d '{
"text": "New clip is live.",
"media": { "media_ids": ["10000000000000001"] }
}'The same result through PostGate
curl -X POST "https://postgate.studio/api/posts?profile_group_id=grp_acme123" \
-H "Authorization: Bearer $POSTGATE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"post": { "body": "Launch day. 🚀" },
"profiles": ["pro_x123"]
}'Frequently asked questions
Why does a tweet with a URL cost more to post?
Under X’s current pay-per-use pricing, a standard post costs $0.015, while the same call with a URL in the text costs $0.200 — the price jumps because a URL triggers X’s link-unfurling and card-preview processing.
How do I attach an image or video to a v2 tweet?
Media isn’t inline in the create request — it’s uploaded separately first through X’s chunked media upload, and the resulting media_id values are referenced by ID in the create-post call under media.media_ids.
What does a successful create-tweet response contain?
The new post’s ID and the text as X actually stored it — useful for confirming that any auto-linked URLs or t.co-wrapped links came through as expected.
Can I post to X without holding X developer credentials?
Yes. PostGate replaces the OAuth 1.0a signing, the direct media/upload state machine, and the create call with one request that also targets every other connected platform. It still costs what X charges for the write — PostGate doesn’t mark that up — but you stop maintaining an X-specific client.
