pixellint

Microsoft CAPI events need eventType, seconds, and a match key

POST JSON to /v1/{tagId}/events. eventType is pageLoad or custom. eventTime is Unix seconds, a 10-digit value. userData needs anonymousId, externalId, em, ph, msclkid, idfa, or gaid. pageLoad needs eventSourceUrl. pageLoadId is a UUID. adStorageConsent is G or D. em is SHA-256 hex. IP and user agent stay unhashed. Browser UET on bat.bing.com is vendor/microsoft-uet.

customData.value needs a currency code

Microsoft documents the ISO 4217 code together with the revenue value. A number without currency is incomplete.

Rule: vendor.microsoft-conversions-api.body.value_requires_currency

What this pack matches

Hosts
capi.uet.microsoft.com
Paths
/v1/
Vendor docs
learn.microsoft.com/en-us/advertising/guides/uet-conversion-api-integration

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
tag_id required It is the numeric UET tag ID, and it travels in the path as /v1/{tagId}/events. Fix: Put the UET tag ID from Microsoft Advertising in the path as /v1/{tagId}/events. vendor.microsoft-conversions-api.param.tag_id.missing
vendor.microsoft-conversions-api.param.tag_id.empty
vendor.microsoft-conversions-api.param.tag_id.invalid
docs
data required Microsoft documents `data` as the list of events. An empty list sends nothing. Native JSON type: array. Minimum array items: 1. Maximum array items: 1000. Fix: Send at least one event in `data`. vendor.microsoft-conversions-api.body.data.missing
vendor.microsoft-conversions-api.body.data.invalid
docs
continueOnValidationError optional It is whether a batch should skip invalid events. Microsoft documents `true` to skip them and `false` (the default) to reject the whole request. Native JSON type: boolean. Fix: Send `true` or `false` in `continueOnValidationError`. vendor.microsoft-conversions-api.body.continueOnValidationError.empty
vendor.microsoft-conversions-api.body.continueOnValidationError.invalid
docs
root optional Each event is a JSON object, rather than a scalar or list. Native JSON type: object. vendor.microsoft-conversions-api.body.root.invalid docs
data[] optional The vendor documents the JSON shape or value type of this field. Native JSON type: object. vendor.microsoft-conversions-api.body.data[].invalid docs
dataProvider optional Third-party senders identify themselves with this request-level string. Native JSON type: string. vendor.microsoft-conversions-api.body.dataProvider.invalid docs
eventType required It is the event type. Microsoft documents `pageLoad` or `custom`. Body scope: data[]. Native JSON type: string. Fix: Set `eventType` to `pageLoad` or `custom`. vendor.microsoft-conversions-api.body.eventType.missing
vendor.microsoft-conversions-api.body.eventType.empty
vendor.microsoft-conversions-api.body.eventType.invalid
docs
eventTime required It is Unix epoch time in seconds UTC. Microsoft documents seconds, so a 13-digit value is milliseconds and the wrong unit. Body scope: data[]. Native JSON type: integer. Fix: Send seconds, a 10-digit Unix timestamp, not milliseconds. vendor.microsoft-conversions-api.body.eventTime.missing
vendor.microsoft-conversions-api.body.eventTime.empty
vendor.microsoft-conversions-api.body.eventTime.invalid
docs
eventId recommended It identifies the event so UET JavaScript and CAPI can deduplicate. Microsoft documents it as required for deduplication. Body scope: data[]. Native JSON type: string. Fix: Set `eventId` to the same value the UET tag sent. vendor.microsoft-conversions-api.body.eventId.missing
vendor.microsoft-conversions-api.body.eventId.empty
vendor.microsoft-conversions-api.body.eventId.invalid
docs
eventName optional It is the custom conversion action. Microsoft documents it for custom conversion goals. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.eventName.empty
vendor.microsoft-conversions-api.body.eventName.invalid
docs
eventSourceUrl optional It is the page URL. Microsoft documents it as required on `pageLoad` events. Body scope: data[]. Native JSON type: string. Fix: Set `eventSourceUrl` to the absolute page URL. vendor.microsoft-conversions-api.body.eventSourceUrl.empty
vendor.microsoft-conversions-api.body.eventSourceUrl.invalid
docs
referrerUrl optional It is the page referrer, used for referral remarketing lists. Microsoft documents a URL. Body scope: data[]. Native JSON type: string. Fix: Send an absolute URL in `referrerUrl`, or omit the field. vendor.microsoft-conversions-api.body.referrerUrl.empty
vendor.microsoft-conversions-api.body.referrerUrl.invalid
docs
pageLoadId optional It links custom events to a page load. Microsoft documents a v4 UUID. Body scope: data[]. Fix: Send a UUID such as `bcf3000b-65fa-4cd2-808a-8a6cf2b1d0a5`. vendor.microsoft-conversions-api.body.pageLoadId.empty
vendor.microsoft-conversions-api.body.pageLoadId.invalid
docs
adStorageConsent optional It is the advertising-storage consent signal. Microsoft documents `G` for granted and `D` for denied. Body scope: data[]. Native JSON type: string. Fix: Set `adStorageConsent` to `G` or `D`. vendor.microsoft-conversions-api.body.adStorageConsent.empty
vendor.microsoft-conversions-api.body.adStorageConsent.invalid
docs
userData required Microsoft documents `userData` as required, with at least one supported identifier. Body scope: data[]. Native JSON type: object. Fix: Add a `userData` object with at least one of `anonymousId`, `externalId`, `em`, `ph`, `msclkid`, `idfa`, or `gaid`. vendor.microsoft-conversions-api.body.userData.missing
vendor.microsoft-conversions-api.body.userData.invalid
docs
userData.anonymousId optional It is the guest visitor ID, also used for ID Sync. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.userData.anonymousId.empty
vendor.microsoft-conversions-api.body.userData.anonymousId.invalid
docs
userData.externalId optional It is an anonymized signed-in user ID. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.userData.externalId.empty
vendor.microsoft-conversions-api.body.userData.externalId.invalid
docs
userData.em optional It is the SHA-256 hex digest of the email. Microsoft documents lowercase hex after trim and lowercase. Body scope: data[]. Value diagnostic severity: warning. Native JSON type: string. Fix: Trim, lowercase, SHA-256, and send 64 lowercase hex characters. vendor.microsoft-conversions-api.body.userData.em.empty
vendor.microsoft-conversions-api.body.userData.em.invalid
docs
userData.ph optional It is the SHA-256 hex digest of the phone number. Body scope: data[]. Value diagnostic severity: warning. Native JSON type: string. Fix: Normalize the phone, SHA-256, and send 64 lowercase hex characters. vendor.microsoft-conversions-api.body.userData.ph.empty
vendor.microsoft-conversions-api.body.userData.ph.invalid
docs
userData.msclkid optional It is the Microsoft Click ID. Microsoft documents it as a UUID. Body scope: data[]. Fix: Send the `msclkid` captured from the landing URL as a UUID. vendor.microsoft-conversions-api.body.userData.msclkid.empty
vendor.microsoft-conversions-api.body.userData.msclkid.invalid
docs
userData.idfa optional It is the iOS Identifier for Advertisers. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.userData.idfa.empty
vendor.microsoft-conversions-api.body.userData.idfa.invalid
docs
userData.gaid optional It is the Android advertising ID. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.userData.gaid.empty
vendor.microsoft-conversions-api.body.userData.gaid.invalid
docs
userData.clientIpAddress optional It is the visitor IP, IPv4 or IPv6, sent unhashed. Microsoft documents it as preferred. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.userData.clientIpAddress.empty
vendor.microsoft-conversions-api.body.userData.clientIpAddress.invalid
docs
userData.clientUserAgent optional It is the visitor user agent, sent unhashed. Microsoft documents it as preferred. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.userData.clientUserAgent.empty
vendor.microsoft-conversions-api.body.userData.clientUserAgent.invalid
docs
customData.currency optional It is the ISO 4217 currency of `customData.value`. Body scope: data[]. Fix: Use a three-letter code such as `USD`. vendor.microsoft-conversions-api.body.customData.currency.empty
vendor.microsoft-conversions-api.body.customData.currency.invalid
docs
customData.value optional It is the revenue value for variable-revenue goals. Microsoft documents a decimal number together with `currency`. Body scope: data[]. Native JSON type: number. Fix: Send a number such as `123.45`, with no currency symbol. vendor.microsoft-conversions-api.body.customData.value.invalid docs
customData.eventValue optional It is the event value for custom conversion goals. Microsoft documents a float. Body scope: data[]. Native JSON type: number. vendor.microsoft-conversions-api.body.customData.eventValue.invalid docs
customData.transactionId optional It is a unique id for singular events such as a purchase. Microsoft documents it as optional but recommended. Body scope: data[]. Native JSON type: string. Fix: Send `customData.transactionId`, or drop the empty pair. vendor.microsoft-conversions-api.body.customData.transactionId.empty
vendor.microsoft-conversions-api.body.customData.transactionId.invalid
docs
customData.pageType optional It is the ecommerce page type for dynamic remarketing. Microsoft documents a closed set. Body scope: data[]. Native JSON type: string. Fix: Set `customData.pageType` to `cart`, `category`, `home`, `other`, `product`, `purchase`, or `searchresults`. vendor.microsoft-conversions-api.body.customData.pageType.empty
vendor.microsoft-conversions-api.body.customData.pageType.invalid
docs
customData.ecommTotalValue optional It is the total value of the cart or purchase. Microsoft documents a decimal. Body scope: data[]. Native JSON type: number. Fix: Send a number such as `123.45`, with no currency symbol. vendor.microsoft-conversions-api.body.customData.ecommTotalValue.invalid docs
customData.items[].id optional It is the item id on an `items` row. Microsoft documents `id` as preferred on each product object. Body scope: data[]. Native JSON type: string. Fix: Set `customData.items[].id` to the catalog item ID, or drop the empty pair. vendor.microsoft-conversions-api.body.customData.items[].id.empty
vendor.microsoft-conversions-api.body.customData.items[].id.invalid
docs
customData.items[].quantity optional It is the item quantity on an `items` row. Microsoft documents an integer. Body scope: data[]. Native JSON type: integer. Fix: Send `customData.items[].quantity` as an integer, such as `2`. vendor.microsoft-conversions-api.body.customData.items[].quantity.empty
vendor.microsoft-conversions-api.body.customData.items[].quantity.invalid
docs
customData.items[].price optional It is the item price after discounts. Microsoft documents a decimal. Body scope: data[]. Native JSON type: number. Fix: Send `customData.items[].price` as a number, such as `25.1`. vendor.microsoft-conversions-api.body.customData.items[].price.invalid docs
customData.hotelData.checkinDate optional It is the hotel check-in date. Microsoft documents `YYYY-MM-DD`. Body scope: data[]. Fix: Send `customData.hotelData.checkinDate` as `YYYY-MM-DD`, such as `2018-10-27`. vendor.microsoft-conversions-api.body.customData.hotelData.checkinDate.empty
vendor.microsoft-conversions-api.body.customData.hotelData.checkinDate.invalid
docs
customData.hotelData.checkoutDate optional It is the hotel check-out date. Microsoft documents `YYYY-MM-DD`. Body scope: data[]. Fix: Send `customData.hotelData.checkoutDate` as `YYYY-MM-DD`, such as `2018-10-31`. vendor.microsoft-conversions-api.body.customData.hotelData.checkoutDate.empty
vendor.microsoft-conversions-api.body.customData.hotelData.checkoutDate.invalid
docs
customData.hotelData.totalPrice optional It is the total booking price including taxes and fees. Microsoft documents a decimal. Body scope: data[]. Native JSON type: number. Fix: Send a number such as `188.23`, with no currency symbol. vendor.microsoft-conversions-api.body.customData.hotelData.totalPrice.invalid docs
customData.hotelData.basePrice optional It is the booking price excluding taxes and fees. Microsoft documents a decimal. Body scope: data[]. Native JSON type: number. Fix: Send a number such as `165.76`, with no currency symbol. vendor.microsoft-conversions-api.body.customData.hotelData.basePrice.invalid docs
customData.hotelData.lengthOfStay optional It is the number of nights. Microsoft documents an integer, and it is not required when `checkoutDate` is sent. Body scope: data[]. Native JSON type: integer. Fix: Send `customData.hotelData.lengthOfStay` as an integer, such as `4`. vendor.microsoft-conversions-api.body.customData.hotelData.lengthOfStay.empty
vendor.microsoft-conversions-api.body.customData.hotelData.lengthOfStay.invalid
docs
root optional Each event is a JSON object, rather than a scalar or list. Body scope: data[]. Native JSON type: object. vendor.microsoft-conversions-api.body.root.invalid docs
customData optional The vendor documents the JSON shape or value type of this field. Body scope: data[]. Native JSON type: object. vendor.microsoft-conversions-api.body.customData.invalid docs
customData.hotelData optional The vendor documents the JSON shape or value type of this field. Body scope: data[]. Native JSON type: object. vendor.microsoft-conversions-api.body.customData.hotelData.invalid docs
customData.items optional The vendor documents the JSON shape or value type of this field. Body scope: data[]. Native JSON type: array. Minimum array items: 1. vendor.microsoft-conversions-api.body.customData.items.invalid docs
customData.items[] optional The vendor documents the JSON shape or value type of this field. Body scope: data[]. Native JSON type: object. vendor.microsoft-conversions-api.body.customData.items[].invalid docs
pageTitle optional The vendor documents the JSON shape or value type of this field. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.pageTitle.invalid docs
keywords optional The vendor documents the JSON shape or value type of this field. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.keywords.invalid docs
customData.searchTerm optional The vendor documents the JSON shape or value type of this field. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.customData.searchTerm.invalid docs
customData.eventCategory optional The vendor documents the JSON shape or value type of this field. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.customData.eventCategory.invalid docs
customData.eventLabel optional The vendor documents the JSON shape or value type of this field. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.customData.eventLabel.invalid docs
customData.itemIds optional The vendor documents the JSON shape or value type of this field. Body scope: data[]. Native JSON type: array. vendor.microsoft-conversions-api.body.customData.itemIds.invalid docs
customData.itemIds[] optional The vendor documents the JSON shape or value type of this field. Body scope: data[]. Native JSON type: string. vendor.microsoft-conversions-api.body.customData.itemIds[].invalid docs
body.user_needs_an_identifier required `userData` carries none of the identifiers Microsoft requires. Send `anonymousId`, `externalId`, `em`, `ph`, `msclkid`, `idfa`, or `gaid`. Body scope: data[]. Fix: Add at least one supported identifier inside `userData`. vendor.microsoft-conversions-api.body.user_needs_an_identifier docs
body.page_load_requires_url required The event is `pageLoad` but carries no `eventSourceUrl`. Microsoft documents the page URL as required on page load events. Body scope: data[]. Fix: Set `eventSourceUrl` to the absolute page URL. vendor.microsoft-conversions-api.body.page_load_requires_url docs
body.value_requires_currency required The event sends `customData.value` without `customData.currency`. Microsoft documents the ISO 4217 code together with the revenue value. Body scope: data[]. Fix: Add `customData.currency`, such as `USD`. vendor.microsoft-conversions-api.body.value_requires_currency docs
body.currency_requires_value required The event sends `customData.currency` without `customData.value`. Microsoft documents both together. Body scope: data[]. Fix: Add `customData.value` as a number, with no currency symbol. vendor.microsoft-conversions-api.body.currency_requires_value docs
body.unhashed_email required `userData.em` carries what looks like a raw email address. Microsoft documents SHA-256 lowercase hex. Body scope: data[]. Fix: Trim, lowercase, hash with SHA-256, and send the 64-character hex digest. vendor.microsoft-conversions-api.body.unhashed_email docs
body.hashed_plaintext_field required This field looks like a SHA-256 digest, but Microsoft documents `clientIpAddress` and `clientUserAgent` as unhashed. Body scope: data[]. Fix: Send the raw IP address or user agent. vendor.microsoft-conversions-api.body.hashed_plaintext_field docs
body.eventTime_time_window required The timestamp is outside the documented processing window. Body scope: data[]. vendor.microsoft-conversions-api.body.eventTime_time_window docs
method required This endpoint documents POST requests. Complete HTTP capture contract. Native JSON type: string. vendor.microsoft-conversions-api.http.method.missing
vendor.microsoft-conversions-api.http.method.empty
vendor.microsoft-conversions-api.http.method.invalid
docs
path required Use the documented event endpoint route. Complete HTTP capture contract. Native JSON type: string. vendor.microsoft-conversions-api.http.path.missing
vendor.microsoft-conversions-api.http.path.empty
vendor.microsoft-conversions-api.http.path.invalid
docs
content_type required The request carries an application/json body. Complete HTTP capture contract. Native JSON type: string. vendor.microsoft-conversions-api.http.content_type.missing
vendor.microsoft-conversions-api.http.content_type.empty
vendor.microsoft-conversions-api.http.content_type.invalid
docs
body_encoding required The event request is encoded as JSON. Complete HTTP capture contract. Native JSON type: string. vendor.microsoft-conversions-api.http.body_encoding.missing
vendor.microsoft-conversions-api.http.body_encoding.empty
vendor.microsoft-conversions-api.http.body_encoding.invalid
docs
headers.authorization required Authenticate with a populated Bearer token. Complete HTTP capture contract. Native JSON type: string. vendor.microsoft-conversions-api.http.headers.authorization.missing
vendor.microsoft-conversions-api.http.headers.authorization.empty
vendor.microsoft-conversions-api.http.headers.authorization.invalid
docs
url required The published request endpoint uses HTTPS. Complete HTTP capture contract. Native JSON type: string. vendor.microsoft-conversions-api.http.url.missing
vendor.microsoft-conversions-api.http.url.empty
vendor.microsoft-conversions-api.http.url.invalid
docs

Validate a payload

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

Try this failing payload in the playground. Microsoft CAPI with a hashed client IP.

{"data":[{"eventType":"custom","eventId":"evt-1","eventTime":1710438591,"userData":{"anonymousId":"b171a9b06ce011ecafcd1b209be8601b","clientIpAddress":"a85e9ca18f34935ab9b0381b25bfad2455444112b0149270fd88e3da172fe196"}}]}

cargo install pixellint · npm install pixellint