X API OpenAPI spec: the one endpoint with no key
The X API OpenAPI spec is a 1.3 MB file at api.x.com/2/openapi.json, free and unauthenticated. It is also a different file every time you fetch it.
On this page · 9 sections
The short version
- ▸GET /2/openapi.json is the only one of 259 operations in the live spec that declares no security requirement. No app, no key, no credit balance, and no rate-limit or price row anywhere in X's docs.
- ▸The file is byte-unstable. Three consecutive fetches returned three different sha256 hashes, because 115 of the 259 operations emit their OAuth scope arrays in a different order each time. Sorting the scope arrays makes every copy identical.
- ▸Version 2.174 holds 201 paths, 259 operations and 886 schemas. X's own machine index at docs.x.com/llms.txt has no section for the Broadcasts, Calls, Bots or Account tags, so 57 of those operations are invisible to anything reading llms.txt.
- ▸Zero operations carry deprecated: true, including the ten Livestream routes X's 5 November 2026 changelog says disappear on 1 January 2027. Generated clients will emit those methods with no warning.
- ▸The widely quoted figure of 190 X API operations is a count of the official Python SDK, not the spec. xdk 0.10.6 exposes 170 methods and was last published on 25 July 2026.
Quick answer
The X API OpenAPI spec lives at GET https://api.x.com/2/openapi.json, it is 1,337,476 bytes of OpenAPI 3.0.0 at spec version 2.174, and it is the only one of the API's 259 operations you can call with no key at all. It is also the most complete index of the API that exists, more complete than X's own documentation index. The catch is that it is a different file on every fetch: three downloads in a row gave three different hashes, because the OAuth scope arrays come back in random order.
Last updated: November 2026
Every number below was measured against the live file on 10 November 2026, cross-checked against X's rate-limit, pricing and versioning pages, the three llms.txt indexes, and the published Python SDK wheel.
What is actually in the file
| Measure | Version 2.174 |
|---|---|
| Size | 1,337,476 bytes |
| OpenAPI version | 3.0.0 |
| Paths | 201 |
| Operations | 259 (125 GET, 77 POST, 40 DELETE, 17 PUT) |
Unique operationIds | 259 |
| Tags | 24 |
| Component schemas | 886 |
Dangling $refs | 0 |
| Operations flagged deprecated | 0 |
Structurally the graph is clean. Every $ref resolves, every operation has a distinct operationId, and only four of the 886 schemas are unreachable from any path, two of which (RulesCount and UploadComplianceJobSubmissionRequest) are never referenced by anything at all. If you want a generated client, this file will produce one without hand-patching.
Tag distribution is where it gets interesting. Users is biggest at 46 operations, but Chat is second at 45 and Broadcasts third at 39, ahead of Posts at 14. The encrypted messaging and livestreaming surfaces are now most of the API by operation count, and neither is where anyone looks. Posts, the thing the X API is known for, is a tenth of it.
The only route with no key
Run this and it works, from a laptop, with nothing configured:
curl -s https://api.x.com/2/openapi.json -o x-openapi.json
That is not an oversight in the docs. In the spec itself, GET /2/openapi.json is the only operation of 259 with no security key, and there is no document-level security requirement for it to fall back to. The other 258 each name at least one scheme: OAuth2UserToken on 216, the OAuth 1.0a UserToken on 197, app-only BearerToken on 88.
Billing matches. X's pay-per-use rate card prices resource categories, not routes, and this route returns no billable resource. And X's rate-limit page, which carries 109 method-and-path rows covering 91 distinct /2/ paths, contains the string openapi exactly zero times. There is no published limit, and the response carries no x-rate-limit-* headers either. Be reasonable about it anyway, because 1.3 MB per call is not free for X.
Two small things make it awkward to automate. api.x.com serves the file with content-disposition: attachment; filename=json.json and cache-control: no-cache, no-store, so a browser downloads it rather than rendering it. The mirror at docs.x.com/openapi.json serves the identical spec inline, with an ETag and a last-modified stamp, behind public, max-age=1800. For a poller, the docs mirror is the friendlier endpoint.
Three fetches, three hashes
This is the part that will cost you an afternoon if nobody warns you.
s1.json 25de66fe...
s2.json a867fe96...
s3.json 84888729...
Three consecutive downloads of the same URL, minutes apart, no version change, identical byte length, three different sha256 values. The spec is not changing. Its serialisation is.
Scope ordering is the cause. Compare the api.x.com copy against the docs.x.com copy and the first difference lands at byte 6,331, inside a POST operation's security block:
api : "OAuth2UserToken": ["dm.write", "tweet.read", "dm.read", "users.read"]
docs : "OAuth2UserToken": ["tweet.read", "users.read", "dm.write", "dm.read"]
Same four scopes, same length, different order. Across the whole file, 115 of the 259 operations differed in scope ordering between two copies, and 144 matched. Nothing else differed. Sorting those arrays made all five copies I had collected, from both URLs, collapse to a single hash.
So the monitoring recipe is one filter wide:
curl -s https://docs.x.com/openapi.json \
| jq -S 'walk(if type=="array" and length>0 and all(.[]; type=="string")
then sort else . end)' \
| shasum -a 256
Store that hash, not the raw one. A naive curl | shasum cron job, or committing the raw file to git, reports a change on every single run, which is exactly the kind of alarm people switch off a week before the real change lands.
There is no cheaper probe, either. HEAD on the file returns 405. A Range: bytes=0-99 request is ignored and hands back all 1,337,476 bytes. The api-version: 2.174 response header is the one thing that would make a change check trivial, but it is absent from the 401 you get by calling any other route without credentials, so you cannot read the version without downloading the spec. Pull the whole file, normalise, hash, diff.
A better index than X's own index
X publishes llms.txt files so that agents can enumerate the docs. The x-api one lists 384 pages across 29 sections. Put it next to the spec and holes appear.
| Spec tag | Operations | Pages in x-api/llms.txt |
|---|---|---|
| Chat | 45 | 16 |
| Broadcasts | 39 | no section |
| Calls | 10 | no section |
| Bots | 6 | no section |
| Account | 2 | no section |
| General | 1 | 1 |
Broadcasts, Calls, Bots and Account are 57 operations between them, and none of the four has a section in the X API index. The pages are not all missing: docs.x.com/livestream-api/sources/overview.md renders fine. But the string livestream appears zero times in the root llms.txt, zero times in the x-api index and zero times in the enterprise index, and the root index lists only four nested indexes, none of which is the Livestream API. An agent that does what X's own AGENTS.md tells it to do, and enumerates from llms.txt, will never find the routes described in X Livestream API.
Chat is the same story in a milder form: 45 operations, 16 reference pages. The spec is the only document that knows the whole API.
Nothing is marked deprecated. Something is.
X's changelog entry of 5 November 2026 is unambiguous. The original Livestream routes under /2/users/:user_id/sources and /2/users/:user_id/broadcasts are deprecated and will be removed on 1 January 2027, after which they return 404.
Those are ten operations in the current spec:
GET|POST /2/users/{id}/broadcasts
GET|DELETE /2/users/{id}/broadcasts/{broadcast_id}
PUT /2/users/{id}/broadcasts/{broadcast_id}/state
GET|POST /2/users/{id}/sources
GET|PUT|DELETE /2/users/{id}/sources/{source_id}
Not one of them carries deprecated: true. Neither does anything else: the count of deprecated operations across all 259 is zero. Every code generator in common use turns that flag into a compiler warning or a doc comment, and X has left it off, so a client generated today ships ten methods with a seven-week shelf life and says nothing about it. If you generate, hard-code that path list into your own lint rule.
X's versioning page compounds this rather than clearing it up. It states that removing an endpoint is a breaking change which "only occurs in major version bumps," while the changelog removes ten endpoints inside /2/. It also never mentions the 2.174 number or the api-version header, so nothing published says what increments that counter or how often. Treat it as an opaque build tag that is useful for diffing and nothing else. The same gap affects which routes have a published ceiling at all, covered in X API rate limits.
Where the "190 endpoints" number comes from
Search for the size of the X API and you will be told it has 190 operations. The freshest third-party index, scored 6 November 2026, four days before this post, says exactly that: "a 190-operation REST surface."
Live, the spec says 259. That gap is not a stale measurement, it is a different object being measured.
X's own Python SDK, xdk 0.10.6, exposes 170 methods across 21 namespace modules. The TypeScript @xdevplatform/xdk 0.6.6 shipped the same day, 25 July 2026, 108 days before this post. Three whole spec tags have no module in either SDK: Account, Bots and Calls. So the published client covers roughly two thirds of the published contract, and any count taken from the SDK, from a Postman collection built on the SDK, or from a docs page tree, comes out near 190 and well under the truth.
This is the recurring shape of X API coverage online, and it is the same mechanism described in X API Python: the SDK is a snapshot, the spec is live, and the SERP measures the snapshot. When a number matters, read the spec. The practical consequence for pricing is the same, since routes the SDK never learned about still bill, which is why X API pricing has to be read against the rate card rather than the client library.
The one thing the spec cannot describe
There is a nice piece of recursion at the bottom of all this. Of 259 operations, 258 declare a real response schema. One declares this:
"200": { "content": { "application/json": { "schema": { "type": "object" } } } }
That one is GET /2/openapi.json. The spec is the only object in the API that the spec does not model, so a generated client hands you an untyped dictionary and you parse it yourself. Which is fine, and faintly appropriate.
A few other structural notes if you are building on it. It is OpenAPI 3.0.0, not 3.1, so nullability is nullable: true (223 occurrences) rather than a type union, and there is no top-level webhooks object even though eight operations are tagged Webhooks. JSON Schema tooling that expects 3.1 will need the older code path. And X's own reference page for this endpoint embeds a static snapshot of the spec header rather than reading the live file, so the version string printed there is only right until the next build. For poking at routes by hand before you generate anything, X API Playground is a faster loop than curl.
When the spec is the wrong map
If you are building a data product, a dashboard, or an agent that reads X at volume, this file is the best artefact X publishes. It is free, it is complete, it predates the docs for every new surface, and normalising it into a committed snapshot gives you a changelog that X does not write. Do that on a weekly timer and you will see new endpoints before the announcement.
If what you want is your own account posting, replying and following on a schedule, the spec will mostly tell you what that costs. Writes are priced per request, the reads around them are priced per resource, and the restrictive part is not the invoice. X-Autopilot takes the browser route instead: your own logged-in session, in your own browser, on your own Mac, so the session cookie never leaves the machine and there is no delegate account or shared cloud IP in the path. That is a lower detection surface than a cloud scheduler, not a safe one, and automating engagement through a browser remains a gray area that X's automation rules speak to directly. The API is the sanctioned route. If you take it, start from the spec and not from a blog post, including this one: curl the file and count it yourself.
Frequently asked
Answers indexed by Google + AI assistants.
Where is the X API OpenAPI spec?+
GET https://api.x.com/2/openapi.json, with no authentication. The same file is mirrored at https://docs.x.com/openapi.json, which adds an ETag and a last-modified header and serves it inline instead of as a download. Both returned 1,337,476 bytes of OpenAPI 3.0.0 at spec version 2.174 on 10 November 2026.
Do I need an API key to download the X OpenAPI spec?+
No. It is the only operation in the spec that declares no security requirement, and there is no global security requirement for it to inherit. The other 258 operations each name at least one of BearerToken, OAuth2UserToken or UserToken. It also returns nothing billable under X's per-resource rate card, and it has no row on the rate-limit page.
How many endpoints does the X API v2 have?+
In version 2.174: 201 paths carrying 259 operations, split 125 GET, 77 POST, 40 DELETE and 17 PUT, across 24 tags and 886 component schemas. Users is the largest tag at 46 operations, followed by Chat at 45 and Broadcasts at 39.
Why does the X OpenAPI spec hash change on every download?+
The OAuth 2.0 scope arrays are serialised in nondeterministic order. Three fetches in a row produced three different sha256 values at identical byte length, and 115 operations differed in scope ordering between two copies taken minutes apart. Normalise before you diff: jq -S 'walk(if type=="array" and length>0 and all(.[]; type=="string") then sort else . end)' collapses every copy to one hash.
Can I generate an X API client from the spec?+
Yes, and it will cover more of the API than the official SDKs do. The spec has no dangling $refs and every operation has a unique operationId, so standard generators run clean. Two caveats: nothing is flagged deprecated, so you will generate the Livestream routes that are scheduled for removal on 1 January 2027, and the spec is OpenAPI 3.0.0 rather than 3.1, so it uses nullable: true and has no top-level webhooks object.
How do I check whether the X API spec changed?+
Download it and compare a normalised hash. There is no cheap probe: HEAD on the file returns 405, a Range request is ignored and returns all 1.3 MB, and the api-version response header that carries the 2.174 string is not present on the 401 you get from an unauthenticated call to any other route.
- X live OpenAPI description at api.x.com/2/openapi.json, version 2.174, read three times and compared: 201 paths, 259 operations with unique operationIds (125 GET, 77 POST, 40 DELETE, 17 PUT), 24 tags, 886 component schemas with no dangling $refs, zero operations flagged deprecated, GET /2/openapi.json as the only operation with no security key and the only bare type: object success schema, scope-usage counts of 216 OAuth2UserToken, 197 UserToken and 88 BearerToken, and the ten /2/users/{id}/sources and /2/users/{id}/broadcasts operations still unflagged (accessed 10 November 2026)
- X developer docs, 'Get OpenAPI Spec': the single page under the General section, which embeds a static snapshot of the spec header at version 2.174 and declares the 200 response as a bare object (accessed 10 November 2026)
- X developer docs machine indexes: docs.x.com/llms.txt, docs.x.com/x-api/llms.txt (384 pages across 29 sections, 16 Chat pages, 1 General page) and docs.x.com/enterprise-api/llms.txt, none of which contain the string 'livestream' or a section for the Broadcasts, Calls, Bots or Account tags, while docs.x.com/livestream-api/sources/overview.md returns 200 (accessed 10 November 2026)
- X API changelog entry dated 5 November 2026, 'Livestream API: new /2/sources and /2/broadcasts routes; /2/users/:user_id routes deprecated', stating the original routes are deprecated and will be removed on 1 January 2027 after which they return 404 (accessed 10 November 2026)
- X developer docs, 'X API Rate Limits': 109 method-and-path rows covering 91 unique /2/ paths, with zero occurrences of the string 'openapi' anywhere on the page (accessed 10 November 2026)
- xdk 0.10.6 for Python, published 25 July 2026, read from the wheel: 21 namespace modules exposing 170 methods, with no module for the Account, Bots or Calls tags; the TypeScript @xdevplatform/xdk 0.6.6 was published the same day (accessed 10 November 2026)
- apis.io provider page for X, Kin Score dated 6 November 2026, describing the X API v2 as 'a 190-operation REST surface' and repeating '190 operations' in its agentic-access breakdown (accessed 10 November 2026)
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 →