pixellint

vendor/x-conversions-api · vendor documented

X conversion API website events

The X Ads measurement conversions endpoint. Website conversion events, contracted as X documents them.

What this pack matches

Hosts
ads-api.twitter.com, ads-api.x.com
Paths
…/measurement/conversions/…
Vendor docs
developer.twitter.com/en/docs/twitter-ads-api/measurement/api-reference/conversions

Rules

Codes are stable. A finding in CI, MCP, or the playground lands on the same id.

Field Required What it checks Rule ids Source
pixel_id required It is the X Pixel ID, and it travels in the path. Fix: Put the Pixel ID in the path as `/12/measurement/conversions/{pixel_id}`. vendor.x-conversions-api.param.pixel_id.missing
vendor.x-conversions-api.param.pixel_id.empty
docs
conversion_time required X documents the conversion time as an ISO 8601 timestamp. Fix: Send an ISO 8601 timestamp, such as `2022-02-18T01:14:00.603Z`. vendor.x-conversions-api.body.conversion_time.missing
vendor.x-conversions-api.body.conversion_time.empty
vendor.x-conversions-api.body.conversion_time.invalid
docs
event_id required It is the conversion event UUID from Ads Manager, not a per-hit dedup key. Fix: Send the conversion event ID from Ads Manager as `event_id`. Use `conversion_id` for dedup. vendor.x-conversions-api.body.event_id.missing
vendor.x-conversions-api.body.event_id.empty
docs
conversion_id optional It is the per-event id used to deduplicate the pixel and the conversion API. Fix: Send the same `conversion_id` the website tag fired. vendor.x-conversions-api.body.conversion_id.empty docs
identifiers[].twclid optional X click identifier from the landing URL. One of the identifiers X requires, along with hashed email or hashed phone. Fix: Send the `twclid` query parameter captured from the click. vendor.x-conversions-api.body.identifiers[].twclid.empty docs
identifiers[].hashed_email optional Email must be trimmed, lowercased, and SHA-256 hashed before it is sent. Fix: Trim and lowercase the address, hash it with SHA-256, and send the hex digest. vendor.x-conversions-api.body.identifiers[].hashed_email.empty
vendor.x-conversions-api.body.identifiers[].hashed_email.invalid
docs
identifiers[].hashed_phone_number optional Phone must be normalized to E.164 and SHA-256 hashed before it is sent. Fix: Normalize to E.164, hash with SHA-256, and send the hex digest. vendor.x-conversions-api.body.identifiers[].hashed_phone_number.empty
vendor.x-conversions-api.body.identifiers[].hashed_phone_number.invalid
docs
identifiers[].ip_address optional It is the visitor IP address, sent unhashed. X documents that IP or user agent must be paired with a second identifier. Fix: Send the raw IP address, and also send `twclid`, `hashed_email`, or `hashed_phone_number`. vendor.x-conversions-api.body.identifiers[].ip_address.empty docs
identifiers[].user_agent optional It is the visitor user agent, sent unhashed. Fix: Send the browser's user agent string, not a digest. vendor.x-conversions-api.body.identifiers[].user_agent.empty docs
price_currency optional It is an ISO 4217 currency code. Fix: Use the three-letter code, such as `USD`. vendor.x-conversions-api.body.price_currency.empty
vendor.x-conversions-api.body.price_currency.invalid
docs
value optional It is the conversion value. X documents `value` on the conversion object, as in `20.00`. Fix: Send `value` as a decimal string, such as `20.00`. vendor.x-conversions-api.body.value.empty
vendor.x-conversions-api.body.value.invalid
docs
number_items optional It is the number of items in the conversion. X documents `number_items` on the conversion object. Fix: Send `number_items` as an integer, such as `3`. vendor.x-conversions-api.body.number_items.empty
vendor.x-conversions-api.body.number_items.invalid
docs
description optional It is a short description of the conversion. X documents `description` on the conversion object. Fix: Send `description`, or drop the empty pair. vendor.x-conversions-api.body.description.empty docs
contents[].content_id optional It is the product id on a contents row. X documents `content_id` on each contents object. Fix: Set `contents[].content_id` to the SKU or catalog id, or drop the empty pair. vendor.x-conversions-api.body.contents[].content_id.empty docs
contents[].content_name optional It is the product name on a contents row. X documents `content_name` on each contents object. Fix: Set `contents[].content_name` to the product name, or drop the empty pair. vendor.x-conversions-api.body.contents[].content_name.empty docs
contents[].content_type optional It is the product category on a contents row. X documents `content_type` on each contents object. Fix: Set `contents[].content_type` to the category, or drop the empty pair. vendor.x-conversions-api.body.contents[].content_type.empty docs
contents[].content_price optional It is the unit price on a contents row. X documents `content_price` on each contents object. Fix: Send `contents[].content_price` as a number, such as `100.99`. Put the order total in `value`. vendor.x-conversions-api.body.contents[].content_price.empty
vendor.x-conversions-api.body.contents[].content_price.invalid
docs
contents[].num_items optional It is the quantity of that product. X documents `num_items` on each contents object. Fix: Send `contents[].num_items` as an integer, such as `1`. vendor.x-conversions-api.body.contents[].num_items.empty
vendor.x-conversions-api.body.contents[].num_items.invalid
docs
contents[].content_group_id optional It is the product group id on a contents row. X documents `content_group_id` on each contents object. Fix: Set `contents[].content_group_id`, or drop the empty pair. vendor.x-conversions-api.body.contents[].content_group_id.empty docs
body.identifier_required required The conversion carries none of the identifiers X requires. Send `twclid`, `hashed_email`, or `hashed_phone_number`. IP and user agent are not enough on their own. Fix: Add a `twclid`, a SHA-256 hashed email, or a SHA-256 hashed phone number. vendor.x-conversions-api.body.identifier_required docs
body.unhashed_email required A field carries what looks like a raw email address. X requires email as `hashed_email`, SHA-256 hashed on the client side. Fix: Trim the address, lowercase it, hash it with SHA-256, and send it as `hashed_email`. vendor.x-conversions-api.body.unhashed_email docs
body.hashed_plaintext_field required This field looks like a SHA-256 digest, but X documents `ip_address` and `user_agent` as unhashed. Fix: Send the raw IP address or user agent. Hashing it makes the event unmatchable. vendor.x-conversions-api.body.hashed_plaintext_field docs

Validate a payload

pixellint validate json @payload.json --rulepack vendor/x-conversions-api

Try this failing payload in the playground. X CAPI without twclid or hashed identity.

{"conversions":[{"conversion_time":"2026-08-21T12:00:00Z","event_id":"1","ip_address":"203.0.113.1"}]}

cargo install pixellint · npm install pixellint