7-day offer$199$9
X-Autopilot

X Custom Audiences API: when a list will not target

Matched 300 users and still cannot target them? The X Custom Audiences API floor is 100 users, the Ads UI floor is 500, and one page states both.

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

The short version

  • ▸There are two minimum sizes, and X's own audiences page states both. An audience is targetable once it matches 100 users active in the last 90 days, but an audience that matches fewer than 500 users will not be available for targeting in the X Ads UI. A list sitting between those numbers works from the API and is invisible in the interface.
  • ▸Match rate has a published formula: 90-day active X users divided by the number of users you provided. Your ceiling is X's active base, not your data hygiene, which is why a clean CRM list can still return a low number.
  • ▸Hashing rules differ by door. The Audience API wants plain SHA-256 with no salt, lowercase hex. The data-partner CRM path wants HMAC-SHA-256 with a key X sends you over PGP. Device IDs use SHA-256 with a salt X provides. And partner_user_id values must not be hashed at all.
  • ▸Payload limits are 2,500 operations and 5,000,000 bytes, at 1,500 requests per minute per account, and the endpoint is atomic: one bad user object fails the whole request, so you fix and resend the entire payload.
  • ▸The global opt-out endpoint is deprecated. Removing an opted-out user is now your bookkeeping: you have to track which audiences they are in and issue a Delete against each one.

Quick answer

The X Custom Audiences API has two different minimum sizes and X's own audiences page publishes both. An audience becomes targetable once it matches at least 100 users active on X in the past 90 days. An audience that matches fewer than 500 users "will not be available for targeting in the X Ads UI". Between those numbers your list is real, matched, API-targetable and absent from the interface. Add the published match-rate formula, which divides 90-day active X users by the number of users you provided, and most "my audience is too small" tickets resolve into arithmetic rather than a bug.

Last updated: November 2026

Every number below comes from X's own Ads API audiences documentation, read on 12 November 2026.

Two floors, one page

Here is the first statement, from the overview:

An audience can only be targeted if it matches at least 100 users active within the past 90 days on X-owned and -operated clients.

And here is the FAQ on the same page, answering what the minimum size is:

The minimum size for an audience to is 100 users (post match). If an audience with less than 500 users is matched, it will not be available for targeting in the X Ads UI.

Both are current. The history explains how they got there: when the Audience API arrived in v4 of the Ads API, two defaults changed at once. The lookback window went from 30 days to 90, and the minimum matched-user count for targeting dropped from 500 to 100. The API floor moved. The interface floor, by X's own description, did not.

For anyone building a tool, that is a specific thing to handle. An audience with 240 matched users is a valid targeting criterion you can attach to a line item through the API, and a client who opens ads.x.com to check your work will not find it. Surface the matched count in your own UI and label anything under 500 as API-only rather than letting the advertiser discover the gap.

Match rate is a definition, not a diagnosis

X publishes the formula in one line:

Match Rate = 90 day active X users / number of users provided

Read the numerator carefully. It is not "users X recognises". It is users X recognises and who have been active in the last 90 days. Two consequences follow, and they are the answer to most low-match-rate questions:

  • Your ceiling is X's active base in your market, not your data quality. A perfectly normalized list of 100,000 customers in a country where X has thin penetration will return a small number. Nothing about the hashing is wrong.
  • Dormant customers are invisible even when matched. Someone who holds an account but has not opened X since spring does not count toward the targetable size.

If you are reporting match rate to a client, report the denominator too. "18% of 40,000" is a fact. "Low match rate" is a support ticket.

There is also a pure timing trap worth knowing before you escalate anything. X states that membership data is added in real time but the job that computes audience size runs later, so a freshly loaded audience can read TOO_SMALL while being entirely fine, with the correct size appearing "after a matter of hours". File processing itself typically takes 4 to 6 hours. The documented threshold for treating it as a real problem is 24 hours.

Three hashing rules for the same email address

This is where integrations actually break, because "hash the emails" means three different things depending on which door you came in through.

PathAlgorithmKey or saltCase
Audience API endpointSHA-256NoneOutput must be lowercase hex
Data-partner CRM matchHMAC-SHA-25632-byte production key, base64, sent over PGPNormalize address first
Device IDs (IDFA, Android ID)SHA-256Common salt X providesNo lowercasing, exact format preserved
partner_user_idNoneNoneSent as-is

That last row is the one that costs people a day. Every other identifier type in an Audience API payload has to be hashed, and X's examples say so in a comment on every snippet. partner_user_id, available to partners who have completed ID Sync, is the exception: those values are sent raw. Hash them and you will get a successful-looking request that matches nobody.

Normalization rules are not uniform either. Email addresses get whitespace stripped and are lowercased. Device IDs get whitespace stripped and are explicitly not lowercased, because the exact IDFA or Android ID casing matters. X usernames are lowercased with the @ omitted, while numeric X user IDs need no normalization at all.

Getting the HMAC key for the CRM path is a human process, not a console setting: you email your public PGP key to X's partner inquiry address, X sends a test message to confirm the channel works, and then sends the key. X will also hand you a test file of sample identifiers and the expected hash output so you can verify your implementation before any real data moves. Ask for it. It is the only way to prove your hashing is right rather than merely silent.

The limits that actually bite

Rate limiting on the Audience API is 1,500 requests per minute per account, which is generous. The payload limits are where the design decisions live:

  • 2,500 operations per request.
  • 5,000,000 bytes maximum payload size.
  • No stated limit on the number of users in a single payload beyond those two constraints.
  • Atomic requests. X is explicit: either the whole request succeeds or the entire request fails. On an error you fix the problem and resend the complete payload, not the failed slice.

Atomicity plus a 2,500-operation cap means batch size is a real engineering choice. Large batches are efficient until one malformed record costs you the whole batch. X's own guidance pushes toward frequent small ones: call the endpoint in near real-time batches rather than spiky bulk jobs, send incremental deltas, and never re-send complete audience memberships. For the initial upload, X says to throttle carefully and expect it to take a significant amount of time.

A successful call returns success_count and total_count. Compare them on every request; that pair is your only confirmation that the objects you sent were the objects X accepted.

Retries should be exponential. X spells out a schedule: immediately on the first failure, after one minute on the second, after five minutes on the third.

Opting a user out is now your bookkeeping

X deprecated the global opt-out endpoint, and nothing replaced it with an equivalent. The current instruction is that partners must Delete any user who has opted out of any audience, and X lists two ways to do it: track which audiences each user belongs to and remove them from each one, or remove the user from every audience on the ad account.

That is a meaningful shift in responsibility. A single "forget me" request no longer maps to a single API call. If you manage audiences for clients, you now need either a membership index of your own or a willingness to issue a Delete against every audience on the account for each opt-out.

One detail softens it: a Delete matches on any key the user was added with. Add someone by email and X user ID, and either key removes them. You do not need to reproduce the exact key combination from the original upload. You can also mix Update and Delete operations in a single request, since the endpoint accepts multiple operation_type values per call.

Each operation also carries effective_at and expires_at timestamps, which is the cleanest way to run a time-boxed audience without a cleanup job.

The deprecated path that outlived its own sunset

The audiences documentation contains a sentence worth reading twice. Introducing the v4 changes, it says the deprecated endpoints "will no longer be available once v3 of the Ads API has been sunset".

Version 3.0 of the Ads API reached end of life on 28 February 2019, according to X's own version table. The current version has been 12.0 since 27 October 2022. Yet the deprecated TON Upload flow, custom_audience_changes, and the global opt-out endpoint are still documented alongside the Audience API, in a comparison table that tells you which parameter to use in each.

Treat that as documentation sediment rather than a live choice. Build on the Audience API path: POST custom_audiences to create the shell, then POST accounts/:account_id/custom_audiences/:custom_audience_id/users with operation_type set to Update or Delete. The list_type parameter that used to declare an audience's identifier type is gone, because an audience can now hold several identifier types for the same user.

One more inherited artifact: several request examples on the page are still written against /11/, and the test-file instructions name a specific advertiser handle to use for ingestion checks. Copy the request shape, not the version number, and use the current /12/ path.

What this costs and who can do it

Custom audiences fall under Standard Access, the broader of the two Ads API tiers, so a Conversion Only approval will not reach them. On top of that, the Audience API endpoint needs an allowlist addition and, if your company accepted the X Ads Products and Services Agreement before 1 August 2018, a re-acceptance of the current one.

Nothing on X's pay-per-usage rate card prices an audience operation, which is consistent with how the rest of the Ads API sits outside the credit system. The access path and the full set of fundamentals are covered in X Ads API, including the authentication question that every Ads API integration now has a deadline on. If your interest is measurement rather than targeting, the two conversion endpoints are a separate product covered in X Conversion API, and they carry their own permission rule: the token has to belong to an account administrator or an ad manager.

Worth knowing on the research side, X ads library lets you see what any advertiser is currently running, which is a faster way to sanity-check a targeting hypothesis than building the audience first. And if the paid side is new to you, what an X ad actually is covers the formats before you automate buying them.

For the organic half of the same account, X-Autopilot runs from your own Mac on your own session and residential IP instead of a shared cloud pool, which lowers the detection surface relative to cloud schedulers without eliminating it. Browser-driven automation of your own account is a gray area X has never endorsed, and we will not tell you otherwise. The Ads API is the opposite case: approved, documented, and rate limited in writing.

The bottom line

Most X custom audience problems are one of four things, and all four are documented. The audience matched between 100 and 499 users, so it works through the API and not in the interface. The match rate is bounded by X's 90-day active base rather than by your data. The hashing rule for the path you used is not the hashing rule you implemented. Or the sizing job simply has not run yet, and the answer is to wait the documented 24 hours before filing anything.

Frequently asked

Answers indexed by Google + AI assistants.

What is the minimum size for an X custom audience?+

Two numbers, both on X's audiences page. An audience can only be targeted if it matches at least 100 users active within the past 90 days on X-owned clients, a floor that dropped from 500 to 100 when the Audience API shipped in v4. The same page's FAQ then says that an audience matching fewer than 500 users will not be available for targeting in the X Ads UI. So between 100 and 499 matched users you have an audience the API will target and the interface will not show.

Why is my X audience showing TOO_SMALL after a large upload?+

Usually timing rather than matching. X's documentation says user data is added to the audience in real time but the job that calculates audience size runs later, so the correct size appears after a matter of hours. Separately, file processing typically takes 4 to 6 hours depending on size. If 24 hours have passed and the audience still will not target, X's own checklist is to verify the user IDs are well formed, the audience names match previous membership updates, the POST responses were successful, and the ID Sync pixel has mapped enough visitors.

How does X calculate audience match rate?+

The published formula is: Match Rate = 90 day active X users / number of users provided. The numerator is the subset of your list that X can match to an account active in the last 90 days. That makes the active-user base the hard ceiling on any match rate, so a list of 100,000 verified email addresses from a market where few people use X will match poorly no matter how clean the data is.

How do I hash emails for the X Custom Audiences API?+

For the Audience API endpoint, SHA-256 with no salt, and the output hex must be lowercase. Normalize first: trim whitespace and lowercase the address. The data-partner CRM path is different: it uses HMAC-SHA-256 with a 32-byte production key X sends base64-encoded over PGP after you email your public key to its partner inquiry address. Device IDs use SHA-256 with a common salt X provides and are not lowercased, since the exact IDFA or Android ID format has to be preserved.

Do I need extra access for the X Audience API?+

Yes. Ads API access alone is not enough. X's prerequisites for the Audience endpoint are Ads API access plus being added to an allowlist via a form, and accepting the current X Ads Products and Services Agreement if your original acceptance predates 1 August 2018.

How do I remove a user who opted out of an X custom audience?+

With the global opt-out endpoint deprecated, you send an operation_type of Delete against each audience the user belongs to. X documents two approaches: track which audiences each user is in and remove them individually, or remove the user from every audience on the ad account. A Delete matches on any key the user was added with, so if you added them by email and X user ID, either key removes them.

Sources
Related searches
x custom audiences apix custom audience minimum sizetwitter tailored audience match ratex ads api audience uploadx custom audience hashing sha256audience too small x adsx custom audience opt outpartner_user_id x audiencex ads apix conversion apix ads manager audiencescrm list upload adsx ads targetingx api oauthaudience match rate
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.