---
title: "Update Article Content"
method: POST
path: "/article/update_content"
tags: ["Articles"]
---

# Update Article Content

`POST /article/update_content`

## Request

- Base URL: `https://api.twitterapis.com/twitter`
- URL: `https://api.twitterapis.com/twitter/article/update_content`
- Auth: HTTP bearer

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; in the shape the X Article editor produces. Blocks are forwarded with only key, text, type, data, entityRanges and inlineStyleRanges; X's schema rejects any other block field (depth included). Block types: unstyled, header-two, unordered-list-item, ordered-list-item, blockquote and atomic (a one-space block that carries an entity through entityRanges). entityMap is an ARRAY of { key, value: { type, mutability, data } }; entity data is snake_case on input and comes back camelCase: TWEET (an embedded post) { tweet_id }, MEDIA (an inline image) { caption, entity_key, media_items: [{ local_media_id, media_category: "DraftTweetImage", media_id }] } with media_id from media/upload, DIVIDER {}, LINK { url } over a text range, MARKDOWN { markdown } for tables. A field X does not know is refused with 422, reason validation_failed and the offending path in detail. Measured live 2026-09-18. Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.

## Request body

- object
  - `id` string, required: The article's base64 entity id, returned by article/create or article/list (the id field, not rest_id).
  - `content_state` string, required: The article body as a Draft.js content-state JSON object: { blocks: [...], entityMap: [...] }, sent as-is in the JSON request body, not as a string field. Blocks carry key, text, type, data, entityRanges, inlineStyleRanges only. entityMap is an array of { key, value: { type, mutability, data } } with snake_case data keys on input (tweet_id, media_items, local_media_id, media_category, media_id, entity_key, url, markdown).

## Response `200`

Replace an article's body with a new Draft.js content_state.

- object
  - `ok` boolean: True when the content was updated.
  - `article` object: The updated article, full shape: id, rest_id, title, preview_text, lifecycle, content_state (your new blocks/entityMap, echoed back), cover_media, media_entities, author, created_at_secs, modified_at_secs, first_published_at_secs, visibility_setting, tweet_id, public_url.

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `402`: Insufficient credits
- `403`: Forbidden
- `404`: Not found
- `429`: Rate limited
- `5XX`: Server error

---

[API](https://skmtc.dev/twitterapis/apis/twitterapis-api.md) · [All operations](https://skmtc.dev/twitterapis/apis/twitterapis-api/llms.txt) · [OpenAPI document](https://skmtc.dev/twitterapis/apis/twitterapis-api/revisions/a33ce0fedb3c?raw)
