Upload Media API
Upload a base64-encoded image as the authenticated account and receive a media_id you can attach when creating a tweet. Runs as your own logged-in account. Billed at $0.0008 per call. Cost: $0.0008 per call.
POST media/upload accepts a base64-encoded image in the request body and uploads it to X (Twitter) under the authenticated account. On success it returns ok:true and a media_id string, which you pass to tweet/create to attach the image to a new tweet. The call is billed at $0.0008.
Authorization
bearerAuth Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/media/upload" \ -H "Content-Type: application/json" \ -d '{ "media_data": "iVBORw0KGgoAAAANSUhEUgAA..." }'{ "ok": true, "media_id": "1899999999999999999"}{ "error": "bad_request", "message": "Missing or malformed parameter. Fix the request before retrying."}{ "error": "unauthorized", "message": "The API key is missing, malformed, or revoked. Check the Authorization header."}{ "error": "insufficient_credits", "message": "Your balance is exhausted. Top up your credits to continue."}{ "error": "forbidden", "message": "The acting account is not authorized for this write action, or has no logged-in session."}{ "error": "not_found", "message": "The resource does not exist, for example a deleted tweet or a private account."}{ "error": "rate_limited", "message": "Too many requests. Back off and retry with exponential backoff."}{ "error": "server_error", "message": "Something failed on our side. Retry with backoff; if it persists, contact support."}Pricing
| Unit | Price |
|---|---|
| Per call | $0.0008 |
| Per 1,000 calls | $0.80 |
When to use
Call this endpoint first whenever a Write Actions request needs to post a tweet containing an image: get a media_id here, then pass it to tweet/create. Use it instead of the other Write Actions endpoints (create_tweet, retweet, favorite_tweet, follow_user) whenever the payload includes a picture, since none of those accept raw image bytes directly.
Notes
- Requires a registered session for the acting account (POST /twitter/customer/session).
- media_data is the base64-encoded image, sent in the JSON request body (not the query string).
Related endpoints
- Media Status: Check the async processing state of an uploaded media_id.
- Like Tweet: Like (favorite) a tweet on behalf of an authenticated account.
FAQ
Can I attach the returned media_id to an existing tweet, or only a new one?
This endpoint only returns a media_id; it does not attach it to anything. You pass that media_id into a separate call to tweet/create when composing a new tweet, since X does not support adding media to a tweet that already exists.
What format does media_data need to be in?
media_data is a required string field sent in the JSON request body containing base64-encoded image bytes. Encode your image file to base64 before sending it; the endpoint does not accept raw binary, multipart form data, or a URL to fetch.
Overview
Write Actions: Act on behalf of an authenticated account: like, retweet, bookmark, and follow, each with its undo. Billed at $0.0008 per call, the same as a standard read.
Media Status GET
Return the async processing state of a media_id from Upload Media, so a caller can verify readiness before attaching a video, GIF, or large-media id to a tweet. Runs as your own logged-in account. Billed at $0.0008 per call. Cost: $0.0008 per call.