pixellint

Heap track calls need app_id and one identity

app_id is the environment ID. event is the custom name, at most 1024 characters. Send identity for a known user or a numeric user_id for Heap's anonymous id, not both. properties must not reuse user_id, session_id, or screen_name. Identify is vendor/heap-identify. Add user properties is vendor/heap-user-properties. Add account properties is vendor/heap-account-properties.

identity and user_id are exclusive

Heap documents one identifier. Sending both is rejected.

Rule: vendor.heap-track.body.identity_and_user_exclusive

What this pack matches

Hosts
heapanalytics.com, c.eu.heap-api.com
Paths
/api/track
Vendor docs
developers.heap.io/reference/track-1

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
app_id required It is the Heap environment ID. Heap documents it as required on every track call. Native JSON type: string. Fix: Set `app_id` to the environment ID from Heap Projects. vendor.heap-track.body.app_id.missing
vendor.heap-track.body.app_id.empty
vendor.heap-track.body.app_id.invalid
docs
events optional Native JSON type: array. Maximum array items: 1000. vendor.heap-track.body.events.invalid docs
events[] optional Native JSON type: object. vendor.heap-track.body.events[].invalid docs
root optional Native JSON type: object. vendor.heap-track.body.root.invalid docs
event required It is the server-side event name. Heap documents it as required, limited to 1024 characters. Body scope: ["events[]",""]. Native JSON type: string. Maximum decoded characters: 1024. Fix: Set `event` to the custom event name, such as `Purchase Completed`, in at most 1024 characters. vendor.heap-track.body.event.missing
vendor.heap-track.body.event.empty
vendor.heap-track.body.event.invalid
docs
identity optional It identifies the user. Heap documents a case-sensitive string of at most 255 characters, and requires either `identity` or `user_id`, not both. Body scope: ["events[]",""]. Native JSON type: string. Maximum decoded characters: 255. Fix: Send the same identity you use in Heap Identify, at most 255 characters. vendor.heap-track.body.identity.empty
vendor.heap-track.body.identity.invalid
docs
user_id optional It is Heap's anonymous user id. Heap documents the string form of a number from 0 through 2^53-1. Body scope: ["events[]",""]. Native JSON type: string. Minimum numeric value: 0. Maximum numeric value: 9007199254740991. Fix: Send the numeric `user_id` from the Heap SDK, digits only. vendor.heap-track.body.user_id.empty
vendor.heap-track.body.user_id.invalid
docs
timestamp optional Heap documents `timestamp` as an ISO 8601 datetime. When omitted, Heap stamps the arrival time. Body scope: ["events[]",""]. Native JSON type: string. Fix: Send an ISO 8601 timestamp, such as `2026-07-26T06:00:00Z`. vendor.heap-track.body.timestamp.empty
vendor.heap-track.body.timestamp.invalid
docs
session_id optional It is an identifier for the user's session. Heap documents `session_id` as a top-level field, not a property key. Body scope: ["events[]",""]. Native JSON type: string. Fix: Send `session_id` at the top level, or drop the empty pair. vendor.heap-track.body.session_id.empty
vendor.heap-track.body.session_id.invalid
docs
idempotency_key optional Heap uses it to drop duplicate track calls. Body scope: ["events[]",""]. Native JSON type: string. vendor.heap-track.body.idempotency_key.empty
vendor.heap-track.body.idempotency_key.invalid
docs
properties.user_id forbidden Heap reserves `user_id` as a top-level field. Reusing it inside `properties` produces unexpected behavior. Body scope: ["events[]",""]. Fix: Rename the property. Send `user_id` at the top level when you have the SDK id. vendor.heap-track.body.properties.user_id.forbidden docs
properties.session_id forbidden Heap reserves `session_id` as a top-level field. Reusing it inside `properties` produces unexpected behavior. Body scope: ["events[]",""]. Fix: Rename the property. Send `session_id` at the top level when you have a session id. vendor.heap-track.body.properties.session_id.forbidden docs
properties.screen_name forbidden Heap documents `screen_name` as reserved because it conflicts with autocaptured Screen Name on mobile. Body scope: ["events[]",""]. Fix: Rename the property. vendor.heap-track.body.properties.screen_name.forbidden docs
properties optional The vendor documents `properties` in the request contract. Body scope: ["events[]",""]. Native JSON type: object. vendor.heap-track.body.properties.invalid docs
property_value… optional The vendor documents `property_value` in the request contract. Body scope: ["events[]",""]. Native JSON type: number or string or array. Maximum decoded characters: 1023. vendor.heap-track.body.property_value.invalid docs
root optional The vendor documents `` in the request contract. Body scope: ["events[]",""]. Native JSON type: object. vendor.heap-track.body.root.invalid docs
overlong_property_names… forbidden Property keys must have fewer than1024characters, counted afterJSONdecoding. Body scope: ["events[]",""]. Presence diagnostic severity: error. vendor.heap-track.body.overlong_property_names.forbidden docs
body.identity_or_user_required required The track call has neither `identity` nor `user_id`. Heap documents one of them as required. Body scope: ["events[]",""]. Fix: Send `identity` for a known user, or `user_id` for an anonymous Heap id. vendor.heap-track.body.identity_or_user_required docs
body.identity_and_user_exclusive required The track call sends both `identity` and `user_id`. Heap documents those as mutually exclusive. Body scope: ["events[]",""]. Fix: Send one identifier, not both. vendor.heap-track.body.identity_and_user_exclusive docs
root optional String arrays are joined with || and values beyond1024Unicodecharacters aretruncated. Body scope: ["events[].properties.*","properties.*"]. Value diagnostic severity: warning. Native JSON type: string or number or boolean or array or object or null. Maximum joined string length: 1024. vendor.heap-track.body.root.invalid docs
method required This published ingestion operation uses HTTP POST. Complete HTTP capture contract. Native JSON type: string. vendor.heap-track.http.method.missing
vendor.heap-track.http.method.empty
vendor.heap-track.http.method.invalid
docs
content_type recommended Use a published request media type. Complete HTTP capture contract. Presence diagnostic severity: warning. Value diagnostic severity: warning. Native JSON type: string. vendor.heap-track.http.content_type.missing
vendor.heap-track.http.content_type.empty
vendor.heap-track.http.content_type.invalid
docs
body required The request body is a JSON object. Complete HTTP capture contract. Native JSON type: object. vendor.heap-track.http.body.missing
vendor.heap-track.http.body.invalid
docs

Validate a payload

pixellint validate json @payload.json --rulepack vendor/heap-track

Try this failing payload in the playground. Heap track with reserved properties.user_id.

{"app_id":"1234567890","identity":"user-10024","event":"Purchase Completed","properties":{"user_id":"nested"}}

cargo install pixellint · npm install pixellint