Update Article Content API
Replace the body of an article you own with a new content_state, identified by its entity id. content_state is Draft.js editor-state JSON ({ blocks: [...], entityMap: [...] }) that you build client-side; it is passed through to X verbatim and not validated on our side. Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.
POST article/update_content replaces the full body of an article you own with a new Draft.js content_state, identified by the article's base64 entity id. It requires a registered session and costs $0.0016 per call. On success it returns ok: true and the updated article object reflecting the new content.
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/article/update_content" \ -H "Content-Type: application/json" \ -d '{ "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4", "content_state": "{\\"blocks\\":[{\\"key\\":\\"a1b2c\\",\\"text\\":\\"Opening paragraph.\\",\\"type\\":\\"unstyled\\",\\"depth\\":0,\\"inlineStyleRanges\\":[],\\"entityRanges\\":[]}],\\"entityMap\\":{}}" }'{ "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": 1786400240, "first_published_at_secs": null, "visibility_setting": null, "tweet_id": null, "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
| Unit | Price |
|---|---|
| Per call | $0.0016 |
| Per 1,000 calls | $1.60 |
When to use
Use this endpoint when you already have an article's entity id and need to overwrite its body with a full new Draft.js content_state, for example after the user edits the article in your own editor and hits save. It replaces the entire body in one call; it does not patch a title (use article/update_title for that) or touch publish state (use article/publish or article/unpublish).
Notes
- [VERIFY] Request variable names inferred from the response field names and the entity id shape; not executed live end-to-end.
- content_state must be valid Draft.js editor-state JSON (blocks[] + entityMap). We do not validate it before sending it to X, so a malformed shape fails on X's side, not ours.
- 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.
- Works on both a draft and an already-published article.
Related endpoints
- Create Article: Start a new draft article. No request body required.
- Update Article Title: Set the title on a draft or published article.
- Publish Article: Publish a draft article. This posts a real, public announcement tweet.
FAQ
What format does content_state need to be in?
content_state is a string containing Draft.js editor-state JSON, the same structure Twitter/X's own article editor produces client-side. You build and serialize this JSON yourself before sending it; the endpoint does not accept plain text or Markdown.
How do I get the id parameter for an article I want to update?
id is the article's base64 entity id, not its URL or slug. Retrieve it from a prior article/create or article/list call's response, then pass that same id string to article/update_content to target that specific article.
Update Article Title POST
Set the title of an article you own, identified by its entity id. Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.
Publish Article POST
Publish a draft article as the account behind your registered session, transitioning it from Draft to Published. WARNING: publishing posts a real, public announcement tweet on the account's timeline. This is not a preview or a private action, and it cannot be undone by re-editing the article: once published, the only way back is Delete Article, which unpublishes the article AND removes the announcement tweet. Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.