TwitterAPIs Docs
API ReferenceWrite Actions

List Draft Tweets API

List every draft on the account behind your registered session. Each row carries the draft id, its text, and thread_truncated, which is true when the draft is a thread and the text you get is only its first tweet. Ordering is X's: pass ascending=true to ask for the oldest first, omit it for X's default. Billed at $0.0016 per call. Cost: $0.0016 per call.

GET draft/list returns every draft saved on the account behind your registered twitterapis session. Each row carries draft_tweet_id, text, and thread_truncated for a thread whose text is only its first tweet. Pass ascending=true to ask X for the oldest first. One call returns the list for $0.0016.

GET
/draft/list

Authorization

bearerAuth
AuthorizationBearer <token>

Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.

In: header

Query Parameters

ascending?boolean

Pass true to ask X for the oldest draft first. Anything else, including omitting it, sends ascending=false, which is what X's own composer sends. The resulting order is X's and is not re-sorted here.

fields?string

Comma-separated list of dotted field paths to keep in the response (one parameter, never repeated), applied to every object in the returned lists and to nested objects (for example fields=id,text,author.username; the list's own name may prefix a path, fields=tweets.id). A path prefix that lands on an array applies to each element (media.media_url_https). Pagination and envelope keys (next_cursor, cursor, has_more, count, partial, error, message, reason) are always kept. Unknown paths are ignored; up to 50 paths of up to 6 segments. Projection never changes status codes or billing, and applies to data reads only: account, feedback, session status, monitor (other than deliveries), webhook and stream-compat reads return their bodies unchanged.

compact?string

Set to 1 (or true) to apply the built-in compact preset: ids, url, text, created_at, lang, the engagement counts, the is_retweet/is_reply/is_quote flags, conversation ids, the author's id/username/name/followers_count/verification, and the quoted or retweeted tweet's id/url/author username. The preset trims what it recognises and leaves alone what it would empty, so it never turns a body into {}. Combine with fields to add paths on top of the preset. Typically cuts a tweet page by 70 to 90 percent for LLM tool callers.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/draft/list?ascending=false&fields=id%2Ctext%2Ccreated_at%2Cauthor.username&compact=1"
{  "drafts": [    {      "draft_tweet_id": "2086650228950683648",      "text": "Draft: our Q1 changelog is nearly done.",      "thread_truncated": false    }  ],  "count": 1}
{  "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.",  "top_up_url": "https://www.twitterapis.com/dashboard/buy-credits?utm_source=api&utm_medium=402"}
{  "error": "forbidden",  "message": "X refused this resource for the acting account: on a read, the account is not a participant in the DM thread, the target is protected or has blocked it, or the session was attestation-blocked for calling from a datacenter or rotating IP; on a write, the account is not authorized for the action or has no logged-in session. The credentials are still valid, so do not re-register."}
{  "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

UnitPrice
Per call$0.0016
Per 1,000 calls$1.60

One call is the whole request, with no cursor to follow, so the per-1,000-records row below is indicative: the number of calls you make depends on how often you poll, not on how many drafts you hold.

When to use

Use draft/list to find the draft_tweet_id you need for an edit or a delete, or to show a human what is waiting for approval. It reads only your own account: there is no way to read another account's drafts, because drafts are private to the account that holds them.

Notes

  • There is no cursor to pass. The only variable X's own composer sends on this operation is ascending, and the response we read carries no cursor of any kind, so one call is the whole request. Whether X itself caps the number of rows it will return has not been observed.
  • There is no created_at. X sends no timestamp on a draft row, so none is invented here; ordering is what ascending controls.
  • NOT BILLED, narrowly: a response that is BOTH partial AND carries no row with usable text costs nothing, even though it answers 200. An honest empty list is NOT that case: it is a correct answer, and it is billed like any other read.
  • Needs a session for the account you are reading: 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.

FAQ

What does partial: true mean here?

It means we read X's answer but did not fully understand all of it: some rows were dropped, or a row's text could not be parsed. It is deliberately different from an empty list. An empty drafts array with no partial flag means the account genuinely has no drafts.

Why is text only the first tweet of my thread?

Because the draft is a thread and this endpoint returns its head. thread_truncated is true on exactly those rows, so you can tell a truncated thread from a complete single tweet rather than silently showing a partial post as whole.

Can I list another account's drafts?

No. Drafts are private to the account that holds them, so this reads only the account behind the session you registered or the inline credentials you passed.

Was this page helpful?