X Ads API: the deadline its own docs never mention
The X Ads API tells you to sign every request with OAuth 1.0a. X retires OAuth 1.0a on 31 January 2027, and not one Ads API page mentions the date.
On this page · 11 sections
- Quick answer
- Two pages, one contradiction
- How buried the date is
- The scopes the Ads API needs are not in the spec
- Access is an application, not an upgrade
- Version 12 has been current for four years
- The rate limit nobody expects
- The sandbox is better than it looks
- The MCP server is the other door
- What to do with this
- The bottom line
The short version
- ▸Every Ads API fundamentals page still says OAuth 1.0a is mandatory. The migration guide on the other side of the doc set says X retires OAuth 1.0a user authentication on 31 January 2027, and that ads-api.x.com already accepts OAuth 2.0 bearer tokens. The two statements have not been reconciled.
- ▸That date appears 7 times in a 4.86 MB documentation corpus, in exactly two pages, and in zero changelog entries. The same day is also the end of life for the Account Activity API.
- ▸The Ads API is a separate approval, not a bigger plan. You apply per developer app through the Ads API Access Form, wait up to 3 business days, and pick Conversion Only or Standard Access. Nothing on the pay-per-use rate card prices any Ads API call.
- ▸Version 12 shipped on 27 October 2022 and is still current. The versioning policy promises a new version for every batch of breaking changes, yet v11 and v12 both show TBD for deprecation and end of life, and new features such as the app conversions endpoint landed inside /12/.
- ▸The limit that catches people is 5 requests per 15 minutes on global reads, meaning any GET without an :account_id in the path. X says it does not raise Ads API rate limits.
Quick answer
The X Ads API is a separate REST API at ads-api.x.com, versioned in the path at /12/, approved per app rather than per plan, and its own fundamentals pages still instruct you to sign every request with OAuth 1.0a. X is retiring OAuth 1.0a user authentication on 31 January 2027. No Ads API page mentions that date, and the only page that does also says ads-api.x.com already accepts OAuth 2.0 bearer tokens. If you are building against the Ads API docs today, you are implementing an auth scheme with a published expiry the docs do not carry.
Last updated: November 2026
Everything below was read on 12 November 2026 against X's own documentation, the flattened corpus at docs.x.com/llms-full.txt, and the live API description at api.x.com/2/openapi.json version 2.174.
Two pages, one contradiction
Start with the Ads API's own instructions. "Making Authenticated Requests" is unambiguous:
All HTTP calls to the Ads API must include an Authorization request header (using OAuth 1.0a) over the HTTPS protocol.
Its rate-limiting page agrees, in passing: "All rate limiting in the Ads API utilizes OAuth 1.0A." The "Accessing Ads accounts" page sends you to a three-legged OAuth 1.0a flow. Across the eleven Ads API pages I pulled, OAuth 1.0a is named eleven times on the auth page alone, and the word Bearer appears zero times outside the MCP page and one aside in the getting-started guide.
Now read the migration guide that lives under authentication fundamentals, titled "Migrate from OAuth 1.0a to OAuth 2.0":
X is retiring OAuth 1.0a user authentication. Apps have until January 31, 2027, to move to OAuth 2.0. After that date, requests signed with OAuth 1.0a stop working.
And further down, its own Ads API section:
The Ads API, including
ads-api.x.com, accepts these OAuth 2.0 user tokens. Migrate your Ads API calls the same way: sendAuthorization: Bearer <access_token>instead of an OAuth 1.0a signature.
So the capability exists, the deadline exists, and the pages a new Ads API integrator actually reads mention neither. That is the whole finding. It is not a subtle reading of a spec; it is two live sentences that cannot both be the current guidance.
How buried the date is
I grepped the flattened doc corpus, all 4,860,318 bytes of it, for the literal string January 31, 2027. Seven hits, spread across two pages: the OAuth migration guide, and the Account Activity API to X Activity API migration page, where the same day is the end of life for AAA.
There is no changelog entry for it. X's changelog does carry a 21 September 2026 entry announcing the token exchange, and that entry describes the mechanism without naming a retirement date. The only 2027 date in the entire changelog is 1 January 2027, for the deprecated livestream routes. An auth retirement that breaks every OAuth 1.0a request on the platform has never been a changelog entry.
Two practical consequences:
- The exchange expires with the thing it replaces. The token exchange needs a working OAuth 1.0a token as input. Any user you have not converted by 31 January 2027 has to go through a fresh consent screen, which for an agency integration means re-asking advertisers for authorization.
- Refresh tokens last about six months. If you lose one after the retirement date, there is no 1.0a token to exchange again. The user signs in or you lose the account.
If you maintain an older X integration of any kind, the mechanics of the exchange are covered in our X API OAuth breakdown, including the permission-to-scope mapping.
The scopes the Ads API needs are not in the spec
ads.read and ads.write are the scopes an OAuth 2.0 token needs to touch ads surfaces. The live API description at api.x.com/2/openapi.json, version 2.174, declares 36 OAuth 2.0 scopes in its security schemes. Neither of them is there.
They do appear in prose: in the permission-mapping table of the migration guide, and throughout the Ads MCP setup instructions. They are real. They are simply absent from the machine-readable contract, which means a code generator or a scope validator built from the spec will reject a perfectly valid ads token. That is the same pattern as the thirteen spec-only scopes documented in the OAuth post, running in the opposite direction.
Access is an application, not an upgrade
Ads API access is not a tier of the X API. It is a separate approval on top of a developer app.
| Step | What it involves |
|---|---|
| Developer app | Create one in the Developer Console, keep its App ID |
| Keys | API key and secret, plus user access tokens, shown once |
| Application | Submit the Ads API Access Form per app, up to 3 business days |
| Tier | Conversion Only, or Standard Access |
| After approval | Regenerate user access tokens, or calls will not authenticate |
Both tiers are narrower than they sound. Conversion Only reaches the mobile and web conversion endpoints and nothing else. Standard Access covers analytics, campaign management, creatives, custom audiences and conversions, and since July 2023 it has absorbed the older split permissions that used to be requested separately. Apps approved before that date can still be stuck on a single permission such as analytics read-only, and can still be capped at five user OAuth tokens, which X will lift only through an account representative.
Then there is a second permission layer you do not control at all. Each X user with access to an ad account holds one of five ad-account-level roles: account administrator, ad manager, campaign analyst, organic analyst, creative manager. Your app's approval does not override them. Two specific traps: tokens used with the web Conversion API must belong to an account administrator or ad manager, and lead exports are restricted to account administrators only, because the exported file contains personal information. Query GET accounts/:account_id/authenticated_user_access before you build a UI that assumes a permission.
Nothing published prices any of this. The pay-per-usage rate card lists its read resources and write actions by name and contains no Ads API row, which is consistent with how X API pricing treats surfaces it has not brought into the credit system. The real cost of the Ads API is the ad spend it manages, not the calls.
Version 12 has been current for four years
X's Ads API versioning policy reads like a disciplined contract. Breaking changes get bundled into a new version. Each new version starts a six-month deprecation clock on the previous one. Two versions are accepted at a time, the older unsupported.
Its version table tells a different story:
| Version | Path | Introduced | Deprecated | End of life |
|---|---|---|---|---|
| 12.0 | /12/ | 27 October 2022 | TBD | TBD |
| 11.0 | /11/ | 31 March 2022 | TBD | TBD |
| 10.0 | /10/ | 31 August 2021 | 31 March 2022 | 27 October 2022 |
Every version up to 10.0 has real dates in both columns. The two current ones have carried TBD for four years. Meanwhile real changes shipped inside /12/: the app conversions endpoint on 29 October 2026, the Google Tag Manager server-side template in September 2026, REGIONS segmentation for analytics. Those arrived as additions, so they did not force a bump, and the versioning page has simply not needed updating since 2022.
Practically, the Ads API version number is stable and is not where you learn what changed. The changelog is. Treat the versioning page as history.
The docs have drifted in smaller ways too. The authenticated-requests page illustrates a path with /6/, the getting-started guide's first twurl example calls /11/accounts, and several in-page links still point at developer.x.com/en/docs/twitter-ads-api/... rather than the current docs.x.com structure. Copy the example, not the version number.
The rate limit nobody expects
Ads API rate limiting has no programmatic index. You discover limits from response headers, and there are two sets: x-rate-limit-* for user-token limits and x-account-rate-limit-* for ad-account limits. X's guidance is to prefer the ad-account headers whenever they are present, because the user-level number on those endpoints is a high global quota for your whole app rather than a per-account budget.
Here is the published chart, per 15-minute window unless noted:
| Scope | Limit |
|---|---|
| Writes, POST/PUT/DELETE, as a category | 450 per minute |
| Audience endpoints, per endpoint | 1,500 per minute |
| Core entity reads, per endpoint, ad account level | 10,000 |
| Other account reads | 2,000 |
| Keyword insights | 500 |
| Targeting criteria, as a category | 400 |
| Audience insights, as a category | 400 |
| Synchronous analytics, as a category | 250 |
| Conversions, per endpoint | 60,000 |
Global reads, GET without an :account_id | 5 |
Five. Global reads means any GET without an ad account in the path, which is the shape of several discovery calls including the GET accounts request the getting-started guide tells you to make first. Loop that while debugging and you will hit a wall inside a minute, with no obvious reason why a working call suddenly stopped.
One more thing worth internalising: the increasing-access page states plainly that X does not raise rate limits for any Ads API endpoint, and the rate-limiting FAQ repeats that they generally cannot be raised because they are already set for the largest advertisers. Design for them. X's own suggestions are the useful ones: sync with sort_by=updated_at-desc against a stored timestamp, batch comma-separated IDs into single requests, and pass the maximum count where an endpoint supports 1,000 instead of the default 200.
The sandbox is better than it looks
ads-api-sandbox.x.com is a full parallel host. Campaigns created there never serve to users, and it exposes six endpoints that do not exist in production: create and delete an advertiser account, add and remove account features, add and remove funding instruments. Call POST accounts and you get an account_id to build against.
That matters more here than on most APIs, because the production path requires an approved app, an advertiser account registered on business.x.com, a funding instrument, and a promotable user before a single campaign call succeeds. The sandbox lets you write the integration while the access form is still in review.
The MCP server is the other door
X also runs a hosted MCP server at ads-api.x.com/mcp, same host, different protocol, with 74 tools covering reads, analytics, targeting, audiences, creatives, media, web event tags, app event tags and writes. It authenticates with the user's own OAuth 2.0 token using ads.read, ads.write and offline.access, and every campaign and line item it creates starts PAUSED, so nothing spends money until something explicitly activates it.
It is the cleanest available demonstration that the OAuth 2.0 path into X advertising works today, since that is the only auth it accepts. One operational detail from its setup guide is worth knowing before you wire several clients: X keeps a single live OAuth grant per app and user, so signing in from a second client revokes the first client's tokens. Register one app per client. Our X MCP server walkthrough covers the three hosted servers and the read-only mode added on 10 November 2026.
What to do with this
If you are starting an Ads API integration now, write OAuth 2.0 from the first commit. The migration guide confirms the host accepts bearer tokens, the MCP server proves the scopes mint and work, and the alternative is implementing HMAC-SHA1 request signing against a scheme with a published death date under three months out.
If you already have one, the order is: enable OAuth 2.0 on the same app that issued your tokens, batch-exchange your stored 1.0a tokens, swap the signature for a bearer header, add a refresh routine, and keep the old tokens until the date passes in case a refresh token is lost. Nothing about that requires your advertisers to do anything.
And if your interest in the Ads API is really about measurement rather than campaign management, the two conversion endpoints are now a separate product with their own auth header, covered in X Conversion API, while the native in-feed form behind X Lead Gen Ads has its own permission rule. Paid reach on X is a different machine from organic reach, and what an X ad actually is is worth reading before you automate buying them.
For the organic side of the same account, X-Autopilot runs on your own Mac with your own session and residential IP rather than through a shared cloud pool, which lowers the detection surface compared with cloud schedulers without removing it. Browser-driven automation of your own account sits in a gray area X has never blessed, and no tool, ours included, can tell you otherwise. The Ads API, by contrast, is a sanctioned surface: approved, documented, and rate limited in writing.
The bottom line
The X Ads API is stable, well specified, and genuinely capable, and it is documented across two sets of pages that currently disagree about how to authenticate. The fundamentals pages describe OAuth 1.0a as a requirement. The migration guide describes it as something that stops working on 31 January 2027 and tells you the Ads host already takes bearer tokens. The migration guide is the one with the date, so it is the one to build against.
Frequently asked
Answers indexed by Google + AI assistants.
What is the X Ads API?+
A separate REST API at ads-api.x.com for managing X advertising from your own code: campaigns, line items, creatives, cards, custom audiences, targeting criteria, lead forms, catalogs and analytics. It is versioned in the URL path, currently /12/, and it is not part of the X API v2 surface at api.x.com. Access is granted per developer app after an application review.
How do I get X Ads API access?+
Create a developer app in the Developer Console, note its App ID, then submit the Ads API Access Form for each app you want approved. X's own introduction page asks for up to 3 business days for review. You choose an access tier on the form: Conversion Only covers the mobile and web conversion endpoints, Standard Access covers analytics, campaign management, creatives, custom audiences and conversions. After approval you have to regenerate your user access tokens before Ads API calls authenticate.
Does the X Ads API still require OAuth 1.0a?+
Its own fundamentals pages say yes. 'Making Authenticated Requests' states that all HTTP calls to the Ads API must include an OAuth 1.0a authorization header, and the rate-limiting page states that all rate limiting in the Ads API uses OAuth 1.0a. X's OAuth migration guide says something different: the Ads API, including ads-api.x.com, accepts OAuth 2.0 user tokens, and you migrate by sending an Authorization: Bearer header instead of a signature. Both pages were live on 12 November 2026.
When does OAuth 1.0a stop working on X?+
31 January 2027, according to the 'Migrate from OAuth 1.0a to OAuth 2.0' guide: 'X is retiring OAuth 1.0a user authentication. Apps have until January 31, 2027, to move to OAuth 2.0. After that date, requests signed with OAuth 1.0a stop working.' The token exchange that converts stored 1.0a tokens silently also stops on that date, so any user you have not migrated has to sign in again.
What are the X Ads API rate limits?+
Per-minute windows: 450 for writes as a category, 1,500 per audience endpoint. Per 15-minute windows: 10,000 per core entity read endpoint at ad account level, 2,000 for other account reads, 400 for targeting criteria and audience insights, 500 for keyword insights, 250 for synchronous analytics, 60,000 for conversions, and 5 for global reads. There is no programmatic index of per-endpoint limits, so you read them from the x-rate-limit and x-account-rate-limit response headers.
Is there a test environment for the X Ads API?+
Yes. Point requests at ads-api-sandbox.x.com instead of ads-api.x.com. Campaigns created there are never served to users, and the sandbox adds six endpoints that do not exist in production so you can create and delete advertiser accounts, account features and funding instruments on demand. Start by calling POST accounts to mint a test account_id.
- X developer docs, Ads API 'Making Authenticated Requests': the ads-api.x.com host, the requirement that all HTTP calls carry an OAuth 1.0a authorization header, the four requirements including an app approved for Ads API access, and the reserved-character encoding table (accessed 12 November 2026)
- X developer docs, 'Migrate from OAuth 1.0a to OAuth 2.0': the statement that apps have until January 31, 2027 to move, the warning that the exchange needs a working OAuth 1.0a token, the OAuth 1.0a versus OAuth 2.0 comparison table, and the Ads API section stating that ads-api.x.com accepts OAuth 2.0 user tokens (accessed 12 November 2026)
- X developer docs, Ads API 'Versions': the full version table showing 12.0 introduced 27 October 2022 with deprecation and end of life both TBD, 11.0 also TBD, and the stated strategy of bundling breaking changes into new versions with a 6-month deprecation window (accessed 12 November 2026)
- X developer docs, Ads API 'Rate limiting': the statement that all rate limiting in the Ads API uses OAuth 1.0a, that there is no programmatic index of per-endpoint limits, the user-level versus ad-account-level header pairs, and the full rate limit chart including 5 per 15 minutes for global reads (accessed 12 November 2026)
- X developer docs, Ads API 'Accessing Ads accounts' and 'Increasing access': the Conversion Only and Standard Access tiers, the five ad-account-level permissions, the Account administrator restriction on lead exports, the pre-July-2023 five-token limit, and the note that X does not increase rate limits for any Ads API endpoint (accessed 12 November 2026)
- X developer docs, Ads API 'Sandbox': the ads-api-sandbox.x.com host, the statement that sandbox campaigns are not served to users, and the six sandbox-only account and funding instrument endpoints (accessed 12 November 2026)
- X developer docs, 'X Ads MCP': the 74 tools at ads-api.x.com/mcp, authentication by the user's own OAuth 2.0 token with ads.read, ads.write and offline.access, campaigns and line items always created PAUSED, and one live OAuth grant per app and user (accessed 12 November 2026)
- X live OpenAPI description at api.x.com/2/openapi.json, version 2.174: the OAuth2UserToken authorization-code flow declares 36 scopes and neither ads.read nor ads.write is among them (fetched and parsed 12 November 2026)
- X developer docs, 'X API Pricing': the complete pay-per-usage read and write tables and the 3 million post read monthly cap, containing no row for any Ads API endpoint (accessed 12 November 2026)
- X developer docs, 'llms-full.txt', the flattened documentation corpus at 4,860,318 bytes: 7 occurrences of 'January 31, 2027' across the OAuth migration guide and the Account Activity API migration page, and zero occurrences of 2027 in any x-ads-api page (fetched and grepped 12 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 →