X Ads API Custom Audiences & Conversion API: The Hashing Rule and Token Gate Nobody Reads

An approved X Ads API app (see our X Ads API access guide) can call every endpoint in the product. That does not mean Custom Audiences and the Conversion API behave the way most integrators expect. Both accept a request, return a success response, and then quietly do nothing useful — because a normalization step was skipped or the wrong token was used.

Custom Audiences: what actually has to be true before upload

Every identifier gets hashed the same exact way

Email, phone, X handle, X user ID, and device ID must each be normalized first (lowercase, trimmed, correct casing per identifier type), then hashed with SHA-256 and no salt, with the output lower-cased. There is no per-identifier variation X will accept.

A mismatch is invisible, not an error

If normalization is wrong — a stray space, an uppercased email, the wrong Android ID casing — the hash simply will not match an X user. The API does not return a validation error for bad hashing; the user is just absent from the audience.

Hard payload ceilings

A single Audience API request is capped at 2,500 operations and 5,000,000 bytes. The Audience endpoint itself carries its own 1,500-request-per-1-minute rate limit, separate from the account-wide limits already covered in our X Ads API rate-limit guide.

A minimum size gate on targeting

An audience only becomes usable for ad targeting once it matches at least 100 users active on X within the past 90 days — a threshold X lowered from 500 users under the current Audience API.

Conversion API: the token check most integrations miss

Ads API access is necessary, not sufficient

Conversion API sits on top of the same Ads API access already covered in our access guide — but that alone does not authorize a token to send conversion events.

The account-role check

Any access token used for Conversion API calls must belong to a user holding AD_MANAGER or ACCOUNT_ADMIN account-level access, verified via the authenticated_user_access endpoint. A token from a Campaign Analyst or Creative Manager role — both valid Ads API roles — will not pass this check.

Identifiers required per event

Every conversion event needs at least one of: X Click ID (twclid, unhashed), a SHA-256-hashed email, or a SHA-256-hashed phone number. IP address and user agent can be sent, but only alongside one of those three — neither works alone.

A published ceiling, cross-checked

Conversion API events are capped at 60,000 per account per 15-minute window — the same figure already listed in our X Ads API rate-limit breakdown, confirming it applies at the account level regardless of which endpoint triggers it.

How the pieces actually connect

  1. An Event Source (X Pixel) and at least one Conversion Event must exist inside Ads Manager before the Conversion API can send anything — the API cannot create the event source itself.
  2. A Custom Audience starts as an empty “shell” created through the Audience API, then users are added or removed against that shell using operation_type Update or Delete.
  3. Every identifier going into that shell is normalized and hashed client-side before it ever reaches X — there is no server-side normalization step to fall back on.
  4. If the same event fires through both the X Pixel and the Conversion API, both must carry the same conversion_id, or the same purchase gets counted twice in reporting.
  5. Before any of this goes to production, the token being used is checked against the AD_MANAGER/ACCOUNT_ADMIN requirement — not just against whether the app has Ads API access.

The numbers that actually matter

100 usersminimum matched, active in 90 days, before an audience is targetable
2,500 / 5MBmax operations and payload size per Audience API request
1,500 / 1 minAudience API's own per-account rate limit
60,000 / 15 minConversion API event ceiling per account

Where syncs quietly break

  • An audience shows “TOO_SMALL” for hours after a large upload — this is a processing-lag artifact of the async matching job, not a rejection.
  • Hashed values never match because a normalization step (spaces, casing, device ID format) was skipped — X returns no “bad hash” error, the user is just never matched.
  • Conversion API calls return HTTP 200 but reporting numbers look inflated — almost always a missing or mismatched conversion_id causing double-counting against the same Pixel event.
  • Conversion API calls fail the permission check even though the app has valid Ads API access — the token belongs to a role below AD_MANAGER/ACCOUNT_ADMIN.

None of this is exotic — it is exactly the kind of integration detail that looks trivial in the reference docs and then costs a week of silently missing conversions or an unusable audience before anyone notices. Preparing this correctly the first time, alongside the access approval and rate-limit handling covered in our other X Ads API guides, is what our X API setup and approval support covers end to end.

Sourced from X's official Ads API documentation (docs.x.com/x-ads-api/audiences and docs.x.com/x-ads-api/measurement/web-conversions), fetched live 2026-08-06.