7-day offer$199$9
X-Autopilot

X API Articles: the block type that returns a 503

The X API Articles endpoints in 2026: a documented heading X confirmed is broken, a DraftJS body with two span conventions, and no price on the rate card.

X-Autopilot Team··9 min read
On this page · 8 sections

The short version

  • ▸Two endpoints, both POST: create a draft, then publish it. They shipped on 11 June 2026 with a one-sentence changelog entry and no forum announcement.
  • ▸header-three is listed as a valid block type in X's live API description and in X's own Python SDK. An X staff member confirmed on 21 July 2026 that it is not supported and returns a bare 503. Three and a half months later the enum still lists it.
  • ▸The body is DraftJS, but X flattened the entity map into an array. entity_ranges keys are integer indexes while entity objects carry string keys, and inline spans use offset and length while mention and URL spans use from_index and to_index in the same object.
  • ▸There is no endpoint to read, edit, delete, unpublish or list Articles. You can create one and publish it, and after that the API has no further opinion about it.
  • ▸Neither endpoint appears on the pay-per-use rate card or in the rate-limit reference. Nothing published tells you what a publish costs or how often you may call it.

Quick answer

X API Articles is two POST endpoints: POST /2/articles/draft to create a draft and POST /2/articles/:article_id/publish to make it public. The body is a DraftJS content state, not markdown and not HTML. One of the eight block types X publishes, header-three, has been confirmed broken by X staff since 21 July 2026 and is still in the schema. There is no endpoint to read, edit, delete or list an Article, and neither endpoint appears on the rate card or in the rate-limit reference.

Last updated: November 2026

Everything below is checked against the live API description at api.x.com/2/openapi.json, version 2.174, and the official Python SDK at version 0.10.6, both read on 6 November 2026.

Two endpoints, and a one-sentence announcement

Articles arrived on 11 June 2026. The changelog entry reads, in full, that X "added new endpoints for drafting and publishing Articles via the X API", with no linked forum post, which is unusual: almost every other entry of that year points at a developer-forum thread with details and a feedback channel.

StepCallSuccessReturns
1POST /2/articles/draft201data.id, data.title
2POST /2/articles/:article_id/publish200data.post_id

Draft IDs are numeric strings of up to 19 digits. The publish response hands back a post ID rather than an article ID, which is the clearest statement of how X models this: a published Article is delivered to timelines as a post that happens to open a long-form page.

Scopes do not agree across sources. X's introduction page says the endpoints need tweet.read, tweet.write and users.read. The live spec attaches an empty scope array to the draft endpoint and tweet.write alone to publish. Request all three, since the narrower reading is the one that breaks silently if it is wrong.

header-three is in the schema and does not work

This is the single most expensive thing to discover yourself.

On 21 July 2026 a developer posted a clean isolation to X's developer forum. Same payload, one block type changed:

{
  "title": "API Header Three Isolation Test",
  "content_state": {
    "blocks": [
      { "text": "Header three isolation test", "type": "header-three" },
      { "text": "Control paragraph.", "type": "unstyled" }
    ],
    "entities": []
  }
}

With header-one or header-two, a draft is created. With header-three, the response is 503 Service Unavailable carrying nothing but {"detail": "Service Unavailable", "status": 503, "title": "Service Unavailable"}. No validation detail, no request ID, nothing that points at the block type. An X staff member replied the same day: header-three is not supported, it results in a 503, and the documentation would be updated to say so.

It was not. Read the live spec today and the block-type enum is unchanged:

Block typeWorks
unstyledyes
header-oneyes
header-twoyes
header-threeno, returns 503
unordered-list-itemdocumented
ordered-list-itemdocumented
blockquotedocumented
atomicyes, required for embeds

X's own Python SDK still types the block as a Literal containing header-three, so the value passes static type checking, passes Pydantic validation, passes the OpenAPI contract, and then fails at the server with a status code that reads like an outage. If you convert markdown or HTML into content state, map h3 and deeper down to header-two and flatten the hierarchy visually instead.

A 503 is also what you get for several unrelated faults, so do not read one as proof of this bug. Strip heading blocks first, confirm the draft lands, then add them back one level at a time.

The body is DraftJS, with the map flattened

content_state takes two required arrays: blocks for text and entities for everything that is not text.

Entities come in seven types, and one of them is doing a lot of work:

Entity typeCarriesNotes
postpost_idembeds an X post
linkurlinline links are entities, not a style
imagemedia_itemsneeds media_id and media_category
emojientity_keymaps to X's internal emoji set
markdownmarkdowncode blocks and tables live here
dividerempty objecthorizontal rule
latexempty objectTeX source goes in the block text

There is no table entity. X's own field description says it outright: tables are not a separate enum value, so you send a pipe table as Markdown inside a markdown entity. Code blocks are the same, as fenced blocks inside that string. So the structured format has an escape hatch into an unstructured one, and the richest parts of an Article pass through it.

Inline formatting is thinner than the composer suggests: bold, italic and strikethrough, and that is the whole set. No underline, no inline code, no highlight.

Flattening is where real DraftJS knowledge turns into a bug. In DraftJS, entityMap is an object keyed by stringified numbers. X ships entities as an array of { key, value } objects where key is a string, while entity_ranges[].key on a block is an integer described as an index into that array. Two fields with the same name, different types, and only one of them actually addresses anything. Build your entity list in order and reference it by position; the string key is decorative.

Two span conventions in the same object

A block can describe spans three ways, and they do not use the same vocabulary.

WhereFields
entity_rangesoffset, length
inline_style_rangesoffset, length
data.mentions, data.hashtags, data.cashtags, data.urlsfrom_index, to_index

So bolding a word is an offset and a length, and tagging a mention in the same sentence is a start index and an end index. Write one span helper and you will get the second family wrong on the first attempt.

That data object is also a reminder that nothing is automatic. Typing @someone into a block's text does not create a mention. You tag the span yourself, which means your own entity extraction has to agree with X's rendering. Get the indexes wrong and the Article publishes with a link over the wrong characters.

Cover media is simpler but still a two-step: upload through the media endpoints first, then pass media_id and a media_category such as tweet_image. The upload flow that actually works is in our notes on X API media upload.

You can write an Article. You cannot read one back

Two paths, both POST. That shapes everything:

  • No GET /2/articles/:id. You cannot read back what you published.
  • No way to list your own drafts. If you lose the ID from the 201 response, the draft is unreachable through the API.
  • No PATCH. A draft cannot be revised; create another.
  • No DELETE and no unpublish.

The reading side exists, but somewhere else and barely. article and article_title are valid post.fields values across about 50 paths, and two expansions, article.cover_media and article.media_entities, appear on 23. The catch is in the schema: article is declared as an object with no properties and no description at all. article_title at least has a description, and it describes itself as metadata about the Article rather than as a title. X added "Get article metadata" on 26 July 2024, nearly two years before the write endpoints, and the shape of what comes back has still never been published.

Editing remains a product feature rather than an API one. Per X's help page the browser flow unpublishes the piece while you work and republishes when you are done, which our guide to X Articles and who can publish them covers along with the subscription tier you need before any of this works at all.

No price, no rate limit

Both tables of the pay-per-use rate card are complete and specific, down to $0.001 per block event. Neither has an Article row.

Three write rows could plausibly apply to a publish: Post: Create at $0.015, Post: Create (with URL) at $0.200 and Content: Manage at $0.005. That is a 40-fold spread on a call you cannot price in advance, and the expensive end is not a silly guess: a published Article is handed back as a post ID, and Articles almost always contain links. Our breakdown of X API pricing covers how the rest of the card bills and what the 24-hour deduplication window does and does not cover.

The rate-limit reference is equally quiet. It carries fourteen per-namespace sections, including two-endpoint namespaces like Communities and Trends, and a catch-all "Other endpoints" table for the leftovers. Articles is in none of them, so the per-15-minute ceiling is unpublished too. The sections that do exist are summarised in X API rate limits.

One more SDK note, since it cuts both ways. The xdk.articles package is in the published wheel with both methods generated and typed, but X's documentation index lists reference pages for xdk.communities and xdk.community_notes and none for xdk.articles. The SDK is ahead of the docs here. Its models are also configured to allow extra fields while the spec forbids them, so the client will happily serialise something the server rejects. The wider gap between the generated client and the hand-written pages is in our notes on the official X API Python SDK.

Who this is actually for

Publishing pipelines. If you already hold long-form content in a structured editor and want it on X without a human in the composer, these two calls are the only sanctioned route, and they work. Budget a day for the content-state converter, map every heading below h2 upward, and keep the draft ID.

For anything else the trade is poor. The format conversion is real work, the Article is write-only once it leaves your system, and you are paying an unpublished price for it. For a single piece, the composer at x.com is faster and gives you editing you cannot get back through the API.

And if the goal behind "publish to X programmatically" is consistent presence rather than long-form specifically, the honest answer is that Articles are the wrong surface, because they need a click to open. X-Autopilot works the other end of that problem, running on your own Mac in your own browser session so there is no shared cloud IP pool and no delegate account in the path. That is a smaller detection surface than a hosted scheduler, not an absent one, and automating engagement through a browser sits in a gray area under X's automation rules rather than being something X sanctions. The Articles endpoints are fully sanctioned. They are also two POSTs and a write-only door.

Frequently asked

Answers indexed by Google + AI assistants.

What are the X API Articles endpoints?+

Two, both POST. POST /2/articles/draft creates a draft Article from a title and a DraftJS content state and returns 201 with the new Article ID, and POST /2/articles/:article_id/publish makes that draft public and returns 200 with the ID of the post created for it. They were added on 11 June 2026. The live API description at version 2.174 contains no other path under /2/articles, so there is no way to read, update, delete or list Articles through the API.

Why does POST /2/articles/draft return 503?+

Most likely a header-three block. A developer isolated the fault on 21 July 2026: identical payloads succeeded with header-one and header-two and failed with header-three, returning a bare HTTP 503 with no validation detail and no request ID. An X staff member replied the same day that header-three is not supported, results in a 503, and that the documentation would be updated. As of 6 November 2026 the live spec and X's official Python SDK both still list header-three as a valid block type, so a schema-valid, type-checked payload can still produce this error.

What format is the X API Article body in?+

DraftJS content state, the rich-text format from Meta's DraftJS editor, with X-specific changes. You send blocks, an array of text blocks with a type from a set of eight, and entities, an array of non-text objects with a type from a set of seven: post, link, image, emoji, markdown, divider and latex. There is no table entity. X's spec says to put a pipe table inside a markdown entity instead. Inline formatting is limited to bold, italic and strikethrough.

How long can an Article created through the X API be?+

The only length figure anywhere in the Articles API is a single sentence inside the description of the markdown entity field, which says the Articles backend enforces a maximum weighted length of 10,000 per article. The title has a minimum length of one character and no published maximum. That 10,000 figure sits oddly against the in-app composer, which X's help page puts at roughly 100,000 characters, so treat it as the figure to design against and test your own ceiling before assuming the larger one applies.

How much does publishing an Article through the X API cost?+

There is no published answer. The pay-per-use rate card has no Article row on either the read or the write table, and the rate-limit reference has no Articles section. The three write rows a publish could plausibly map to are Post: Create at $0.015, Post: Create (with URL) at $0.200 and Content: Manage at $0.005, a 40-fold spread. Since a published Article is delivered as a post and Articles usually contain links, check your credit balance before and after your first publish rather than guessing.

Can you edit or delete an Article through the X API?+

No. The only two paths are draft creation and publish. There is no GET, PATCH or DELETE under /2/articles, no way to list your drafts and no way to unpublish. Editing an Article is still a browser task: X's help page describes opening the piece, choosing Edit Article, which unpublishes it while you work, then republishing. Anything you publish through the API can only be revised through the product.

Sources
Related searches
x api articles/2/articles/draftx api publish articlex articles api content_statex api draftjs articlex api article header-three 503twitter articles api v2x api article character limitx articlesx api pricingx api rate limitsx api media uploadx api v2 endpointslong form content on xx premium price
DY
Deepak YadavBuilding X-Autopilot

Product designer and indie hacker. Runs the agent on his own X account every day and writes up what the data shows, including when it's inconvenient.

Follow on X →
Try X-Autopilot.
7-day offer: $199 $9 once. No subscription, no monthly bill. Real Chrome on your Mac.
See pricing▶
Free PDF · the X Growth Playbook

The exact playbook we use to grow on X

The bio that converts, the daily reply loop, the posting cadence, and the tool stack, in one no-fluff PDF. Drop your email and it's yours.

No spam. Unsubscribe anytime.

Free tools

Try it yourself.

All free X tools →
Keep reading

Related posts.