7-day offer$199$9
X-Autopilot

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.

X-Autopilot Team··11 min read
On this page · 11 sections

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: send Authorization: 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.

StepWhat it involves
Developer appCreate one in the Developer Console, keep its App ID
KeysAPI key and secret, plus user access tokens, shown once
ApplicationSubmit the Ads API Access Form per app, up to 3 business days
TierConversion Only, or Standard Access
After approvalRegenerate 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:

VersionPathIntroducedDeprecatedEnd of life
12.0/12/27 October 2022TBDTBD
11.0/11/31 March 2022TBDTBD
10.0/10/31 August 202131 March 202227 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:

ScopeLimit
Writes, POST/PUT/DELETE, as a category450 per minute
Audience endpoints, per endpoint1,500 per minute
Core entity reads, per endpoint, ad account level10,000
Other account reads2,000
Keyword insights500
Targeting criteria, as a category400
Audience insights, as a category400
Synchronous analytics, as a category250
Conversions, per endpoint60,000
Global reads, GET without an :account_id5

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.

Sources
Related searches
x ads apix ads api accessx ads api oauth 1.0atwitter ads api authenticationx ads api rate limitsads-api.x.com sandboxx ads api version 12how to get x ads api accessx ads managerx conversion apix api oauth scopesx ads mcpx lead gen adsx api pricingad account permissions
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.