Create Draft Tweet API
Save a draft tweet on the account behind your registered session. A draft is private to that account and is never published: it appears in X's own composer under Drafts until you post or delete it. Accepts text, up to 4 media_ids, a reply_to and a quote, exactly like tweet/create. Billed at $0.0016 per call. Cost: $0.0016 per call.
POST draft/create saves a private draft tweet on the account behind your registered twitterapis session. Nothing is posted: the draft appears in X's own composer under Drafts until you publish or delete it. It takes text plus optional media_ids, reply_to and quote, and returns ok and draft_tweet_id for $0.0016 a call.
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/draft/create" \ -H "Content-Type: application/json" \ -d '{ "text": "Draft: our Q1 changelog is nearly done." }'{ "ok": true, "draft_tweet_id": "2086650228950683648"}{ "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.0016 |
| Per 1,000 calls | $1.60 |
When to use
Use draft/create when a human still has to approve the wording before anything goes public, so the copy sits in X's own composer rather than in your database. Reach for tweet/create when the post should go out immediately, and scheduled/create when it should go out on its own at a known future time.
Notes
- A draft is PRIVATE. It is never posted by this endpoint or by any timer; only you posting it from X's composer publishes it.
- Needs a session for the account you are acting as: either register one once (POST /customer/session), or pass per-call inline credentials as x-auth-token and x-ct0 request headers, which let a single API key act as many accounts. Returns 409 session_required if neither is supplied, 401 session_dead when the session has expired.
- Upload media via media/upload first to get media_ids; up to 4 images per draft.
- A 19-digit reply_to or quote sent as an UNQUOTED JSON number is refused rather than silently rounded to a different tweet. Send IDs as strings.
Related endpoints
- Edit Draft Tweet: Replace the contents of an existing draft on your own account.
- List Draft Tweets: List the drafts saved on your own account.
- Delete Draft Tweet: Delete a draft from your own account by ID.
- Create Tweet: Post a tweet as your registered account: text, media, reply, or quote.
FAQ
Does creating a draft post anything to my timeline?
No. A draft is private to the account that owns it and stays in X's composer under Drafts. Nothing is published until you post it yourself, and there is no timer attached to a draft. Use scheduled/create if you want a post to go out on its own.
Can I create a draft with only an image and no text?
No. This endpoint refuses a draft with no text and answers 400 with a bad_request body. Put at least a placeholder line in text, then attach media_ids alongside it.
What happens if X refuses the create?
draft_tweet_id comes back null, the response is 422 rather than a misleading 200, and the call is not billed. Check ok before reading draft_tweet_id.
Delete Tweet POST
Delete a tweet owned by the account behind your registered session. Identify it by id or url (read from the query string). Requires a registered session. Billed at $0.0008 per call, the same as a standard read. Cost: $0.0008 per call.
Edit Draft Tweet POST
Replace an existing draft's contents on the account behind your registered session. The fields you send become the draft in full: text is required, and media_ids, reply_to and quote are re-applied rather than merged, so send everything the draft should keep. Billed at $0.0016 per call. Cost: $0.0016 per call.