TwitterAPIs Docs
API ReferenceArticles

Unpublish Article API

Revert a Published article back to Draft, identified by its entity id. The announcement tweet the original publish posted is left in place; use Delete Article to remove it too. X server-validates this transition and returns a 422 (invalid_lifecycle) if the article is not currently Published. Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.

POST article/unpublish reverts a Published article back to Draft status without deleting its announcement tweet. It requires a registered session and the article's base64 entity id. It returns 422 if the article is not currently Published, and on success returns ok: true plus the updated article object. Billed at $0.0016 per call.

POST
/article/unpublish

Authorization

bearerAuth
AuthorizationBearer <token>

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/article/unpublish" \  -H "Content-Type: application/json" \  -d '{    "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4"  }'
{  "ok": true,  "article": {    "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4",    "rest_id": "2086650228950683648",    "title": "Why we rebuilt our onboarding from scratch",    "preview_text": "Opening paragraph.",    "lifecycle": "Draft",    "content_state": {      "blocks": [        {          "key": "a1b2c",          "text": "Opening paragraph.",          "type": "unstyled",          "depth": 0,          "inlineStyleRanges": [],          "entityRanges": []        }      ],      "entityMap": []    },    "cover_media": null,    "media_entities": [],    "author": {      "id": "44196397",      "username": "elonmusk",      "name": "Elon Musk"    },    "created_at_secs": 1786400000,    "modified_at_secs": 1786400500,    "first_published_at_secs": 1786400400,    "visibility_setting": null,    "tweet_id": "2086650300012345678",    "public_url": null  }}
{  "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

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

When to use

Use this endpoint when a published article needs to be pulled back to Draft for edits or review while keeping its original announcement tweet intact. Reach for Delete Article instead if the tweet itself also needs to come down.

Notes

  • [VERIFY] Request variable names inferred; the 422 invalid_lifecycle validation is server-side on X's end, not executed live end-to-end.
  • The announcement tweet from the original publish is left in place. To remove it too, call Delete Article instead.
  • Returns 422 if the article is not currently Published (for example, it is already a Draft).
  • Needs a session for the account you are writing 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.
  • Publish Article: Publish a draft article. This posts a real, public announcement tweet.
  • Delete Article: Delete an article. A draft is hard-deleted; a published article is unpublished, then its announcement tweet is removed too.
  • Update Article Content: Replace an article's body with a new Draft.js content_state.

FAQ

Does unpublishing an article also remove the tweet that announced it?

No. The announcement tweet stays live. article/unpublish only reverts the article's status to Draft. If you need the tweet gone as well, call Delete Article instead, which removes both.

What happens if I call this on an article that's already a Draft?

The endpoint returns a 422 error. It only succeeds on articles currently in Published status, so check the article's status (via Get Article or List Articles) before calling this if you're not certain of its current state.