pixellint

vendor/braze · vendor documented

Braze user track wants ISO 8601, not epoch

events[].time and purchases[].time are ISO 8601 datetimes. An epoch number fails the contract. Every event and purchase needs one of external_id, user_alias, braze_id, email, or phone. Sending two primary identifiers rejects the object.

A purchase also needs product_id, an ISO 4217 currency code, and a numeric price. Quantity, when sent, is 1 through 100. A symbol like $ is not a currency code. Custom properties must not reuse reserved names such as time.

What this pack matches

Hosts
braze.com, braze.eu
Paths
…/users/track…
Vendor docs
www.braze.com/docs/api/endpoints/user_data/post_user_track/

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
external_id optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.external_id.empty docs
user_alias optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.user_alias.empty docs
braze_id optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.braze_id.empty docs
email optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.email.empty docs
phone optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.phone.empty docs
app_id optional It is the App Identifier. Braze documents it as optional on events. Fix: Send `app_id` as the App Identifier from Braze, or drop the empty pair. vendor.braze.body.app_id.empty docs
user_alias.alias_name optional It is the alias identifier. Braze documents it as required on a user alias object, at most 236 bytes. Fix: Set `user_alias.alias_name` to a non-empty identifier of at most 236 bytes. vendor.braze.body.user_alias.alias_name.empty
vendor.braze.body.user_alias.alias_name.invalid
docs
user_alias.alias_label optional It is the alias type. Braze documents it as required on a user alias object, at most 236 bytes. Fix: Set `user_alias.alias_label` to a non-empty label of at most 236 bytes. vendor.braze.body.user_alias.alias_label.empty
vendor.braze.body.user_alias.alias_label.invalid
docs
name required Braze documents the event name as required. Fix: Name the custom event. vendor.braze.body.name.missing
vendor.braze.body.name.empty
docs
time required Braze documents the event time as an ISO 8601 datetime, such as `2026-07-26T06:00:00+00:00`. Fix: Send an ISO 8601 datetime rather than an epoch number. vendor.braze.body.time.missing
vendor.braze.body.time.empty
vendor.braze.body.time.invalid
docs
_update_existing_only optional Braze documents this as a boolean. When true, the call updates an existing profile and does not create one. vendor.braze.body._update_existing_only.empty
vendor.braze.body._update_existing_only.invalid
docs
properties.time forbidden Braze reserves `time` as an event field, not as a custom property name. Fix: Rename the property. `time` is reserved. vendor.braze.body.properties.time.forbidden docs
properties.event_name forbidden Braze reserves `event_name` and cannot use it as a custom property. Fix: Rename the property. `event_name` is reserved. vendor.braze.body.properties.event_name.forbidden docs
body.event_one_primary_identifier required The event carries more than one primary identifier. Braze documents one of `external_id`, `user_alias`, or `braze_id` per object, and rejects the object when two are sent. Fix: Send one primary identifier. `email` and `phone` may ride alongside it as attributes. vendor.braze.body.event_one_primary_identifier docs
body.event_needs_an_identifier required The object carries none of `external_id`, `user_alias`, `braze_id`, `email`, or `phone`. Braze documents one of them as required, and cannot attach the data to a user without one. Fix: Add one of the documented identifiers to the object. vendor.braze.body.event_needs_an_identifier docs
body.event_alias_requires_name_and_label required A `user_alias` object is missing `alias_name` or `alias_label`. Braze documents both as required, each at most 236 bytes. Fix: Set `user_alias.alias_name` and `user_alias.alias_label`. vendor.braze.body.event_alias_requires_name_and_label docs
external_id optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.external_id.empty docs
user_alias optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.user_alias.empty docs
braze_id optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.braze_id.empty docs
email optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.email.empty docs
phone optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.phone.empty docs
app_id optional It is the App Identifier. Braze documents it as optional on purchases. Fix: Send `app_id` as the App Identifier from Braze, or drop the empty pair. vendor.braze.body.app_id.empty docs
user_alias.alias_name optional It is the alias identifier. Braze documents it as required on a user alias object, at most 236 bytes. Fix: Set `user_alias.alias_name` to a non-empty identifier of at most 236 bytes. vendor.braze.body.user_alias.alias_name.empty
vendor.braze.body.user_alias.alias_name.invalid
docs
user_alias.alias_label optional It is the alias type. Braze documents it as required on a user alias object, at most 236 bytes. Fix: Set `user_alias.alias_label` to a non-empty label of at most 236 bytes. vendor.braze.body.user_alias.alias_label.empty
vendor.braze.body.user_alias.alias_label.invalid
docs
product_id required Braze documents the product id as required on a purchase, at most 255 characters. Fix: Send a product name or category of at most 255 characters. vendor.braze.body.product_id.missing
vendor.braze.body.product_id.empty
vendor.braze.body.product_id.invalid
docs
currency required Braze documents the currency as required on a purchase, as an ISO 4217 code. Fix: Use the three-letter code, such as `USD`. vendor.braze.body.currency.missing
vendor.braze.body.currency.empty
vendor.braze.body.currency.invalid
docs
price required Braze documents the price as a float in the currency's base unit, such as dollars for USD. Fix: Send a number such as `129.99`, with no currency symbol. vendor.braze.body.price.missing
vendor.braze.body.price.empty
vendor.braze.body.price.invalid
docs
quantity optional Braze documents quantity as an integer from 1 through 100, defaulting to 1. Fix: Send an integer from 1 to 100. vendor.braze.body.quantity.empty
vendor.braze.body.quantity.invalid
docs
time required Braze documents the purchase time as an ISO 8601 datetime. Fix: Send an ISO 8601 datetime rather than an epoch number. vendor.braze.body.time.missing
vendor.braze.body.time.empty
vendor.braze.body.time.invalid
docs
_update_existing_only optional Braze documents this as a boolean. When true, the call updates an existing profile and does not create one. vendor.braze.body._update_existing_only.empty
vendor.braze.body._update_existing_only.invalid
docs
properties.time forbidden Braze reserves `time` and cannot use it as a purchase property name. Fix: Rename the property. `time` is reserved. vendor.braze.body.properties.time.forbidden docs
properties.product_id forbidden Braze reserves `product_id` and cannot use it as a purchase property name. Fix: Rename the property. `product_id` is reserved. vendor.braze.body.properties.product_id.forbidden docs
properties.quantity forbidden Braze reserves `quantity` and cannot use it as a purchase property name. Fix: Rename the property. `quantity` is reserved. vendor.braze.body.properties.quantity.forbidden docs
properties.event_name forbidden Braze reserves `event_name` and cannot use it as a purchase property name. Fix: Rename the property. `event_name` is reserved. vendor.braze.body.properties.event_name.forbidden docs
properties.price forbidden Braze reserves `price` and cannot use it as a purchase property name. Fix: Rename the property. `price` is reserved. vendor.braze.body.properties.price.forbidden docs
properties.currency forbidden Braze reserves `currency` and cannot use it as a purchase property name. Fix: Rename the property. `currency` is reserved. vendor.braze.body.properties.currency.forbidden docs
body.purchase_one_primary_identifier required The purchase carries more than one primary identifier. Braze documents one of `external_id`, `user_alias`, or `braze_id` per object, and rejects the object when two are sent. Fix: Send one primary identifier. `email` and `phone` may ride alongside it as attributes. vendor.braze.body.purchase_one_primary_identifier docs
body.purchase_needs_an_identifier required The object carries none of `external_id`, `user_alias`, `braze_id`, `email`, or `phone`. Braze documents one of them as required, and cannot attach the data to a user without one. Fix: Add one of the documented identifiers to the object. vendor.braze.body.purchase_needs_an_identifier docs
body.purchase_alias_requires_name_and_label required A `user_alias` object is missing `alias_name` or `alias_label`. Braze documents both as required, each at most 236 bytes. Fix: Set `user_alias.alias_name` and `user_alias.alias_label`. vendor.braze.body.purchase_alias_requires_name_and_label docs
external_id optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.external_id.empty docs
user_alias optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.user_alias.empty docs
braze_id optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.braze_id.empty docs
email optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.email.empty docs
phone optional Braze documents one of external_id, user_alias, braze_id, email, or phone as required on every object. vendor.braze.body.phone.empty docs
user_alias.alias_name optional It is the alias identifier. Braze documents it as required on a user alias object, at most 236 bytes. Fix: Set `user_alias.alias_name` to a non-empty identifier of at most 236 bytes. vendor.braze.body.user_alias.alias_name.empty
vendor.braze.body.user_alias.alias_name.invalid
docs
user_alias.alias_label optional It is the alias type. Braze documents it as required on a user alias object, at most 236 bytes. Fix: Set `user_alias.alias_label` to a non-empty label of at most 236 bytes. vendor.braze.body.user_alias.alias_label.empty
vendor.braze.body.user_alias.alias_label.invalid
docs
_update_existing_only optional Braze documents this as a boolean. When true, the call updates an existing profile and does not create one. vendor.braze.body._update_existing_only.empty
vendor.braze.body._update_existing_only.invalid
docs
push_token_import optional Braze documents this as a boolean used when importing anonymous push tokens. vendor.braze.body.push_token_import.empty
vendor.braze.body.push_token_import.invalid
docs
gender optional Braze documents gender as `M`, `F`, `O`, `N`, `P`, or null. Fix: Send `M`, `F`, `O`, `N`, or `P`, or omit the field. vendor.braze.body.gender.empty
vendor.braze.body.gender.invalid
docs
email_subscribe optional Braze documents email subscription as `opted_in`, `unsubscribed`, or `subscribed`. Fix: Send `opted_in`, `unsubscribed`, or `subscribed`. vendor.braze.body.email_subscribe.empty
vendor.braze.body.email_subscribe.invalid
docs
push_subscribe optional Braze documents push subscription as `opted_in`, `unsubscribed`, or `subscribed`. Fix: Send `opted_in`, `unsubscribed`, or `subscribed`. vendor.braze.body.push_subscribe.empty
vendor.braze.body.push_subscribe.invalid
docs
dob optional Braze documents date of birth as `YYYY-MM-DD`. Fix: Send the date of birth as `YYYY-MM-DD`, such as `1980-12-21`. vendor.braze.body.dob.empty
vendor.braze.body.dob.invalid
docs
body.attribute_one_primary_identifier required The attribute object carries more than one primary identifier. Braze documents one of `external_id`, `user_alias`, or `braze_id` per object, and rejects the object when two are sent. Fix: Send one primary identifier. `email` and `phone` may ride alongside it as attributes. vendor.braze.body.attribute_one_primary_identifier docs
body.attribute_needs_an_identifier required The object carries none of `external_id`, `user_alias`, `braze_id`, `email`, or `phone`. Braze documents one of them as required, and cannot attach the data to a user without one. Fix: Add one of the documented identifiers to the object. vendor.braze.body.attribute_needs_an_identifier docs
body.attribute_alias_requires_name_and_label required A `user_alias` object is missing `alias_name` or `alias_label`. Braze documents both as required, each at most 236 bytes. Fix: Set `user_alias.alias_name` and `user_alias.alias_label`. vendor.braze.body.attribute_alias_requires_name_and_label docs

Validate a payload

pixellint validate json @payload.json --rulepack vendor/braze

Try this failing payload in the playground. Braze event with two primary identifiers.

{"events":[{"external_id":"user-10024","braze_id":"braze-77","name":"order_placed","time":"2026-07-26T06:00:00+00:00"}]}

cargo install pixellint · npm install pixellint