Mixpanel import needs time, distinct_id, and $insert_id
The /import endpoint is a batch of events with no properties.token, unlike /track. time is required Unix seconds or milliseconds. $insert_id is required so a retry is not counted twice, and it must be at most 36 alphanumeric or hyphen characters. Placeholder ids such as null or 0 are rejected. An empty distinct_id is allowed when there is no user. strict=1 is recommended so failed events are named in the response.
$insert_id is required on import
Track recommends it. Import rejects the event without it. Mixpanel uses it to drop duplicates. Underscores and strings longer than 36 characters fail the published format.
Rule: vendor.mixpanel-import.body.properties.$insert_id.empty
Placeholder distinct_ids are rejected
Mixpanel publishes a list of values it will not ingest, including null, 0, anonymous, and the all-zero UUID. An empty distinct_id is the documented way to send an event with no user.
What this pack matches
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 |
|---|---|---|---|---|
strict |
recommended | Mixpanel documents `strict=1` so the batch is validated and failed events are named in the response. Fix: Send `strict=1` on `/import`. | vendor.mixpanel-import.param.strict.missingvendor.mixpanel-import.param.strict.emptyvendor.mixpanel-import.param.strict.invalid |
docs |
project_id |
optional | It is the Mixpanel project id. Mixpanel requires it for service-account auth, and token auth may omit it. Fix: Send `project_id` with a service account, or drop the empty pair. | vendor.mixpanel-import.param.project_id.empty |
docs |
https_required |
required | Mixpanel explicitly rejects non-HTTPS API requests. | vendor.mixpanel-import.https_required |
docs |
|
optional | The JSON body is a nonempty array of records. Native JSON type: array. Minimum array items: 1. | vendor.mixpanel-import.body..invalid |
docs |
event |
required | Mixpanel documents the event name as required on every imported event. Body scope: []. Native JSON type: string. Fix: Name the event, such as `Signup`. | vendor.mixpanel-import.body.event.missingvendor.mixpanel-import.body.event.emptyvendor.mixpanel-import.body.event.invalid |
docs |
properties |
required | Mixpanel documents the properties object as required. `time`, `distinct_id`, and `$insert_id` ride inside it. Body scope: []. Native JSON type: object. Maximum object properties: 254. Fix: Add a `properties` object carrying `time`, `distinct_id`, and `$insert_id`. | vendor.mixpanel-import.body.properties.missingvendor.mixpanel-import.body.properties.invalid |
docs |
properties.time |
required | Mixpanel documents `time` as required Unix seconds or milliseconds since epoch. Body scope: []. Native JSON type: integer. Fix: Send seconds or milliseconds since epoch, as an integer. | vendor.mixpanel-import.body.properties.time.missingvendor.mixpanel-import.body.properties.time.emptyvendor.mixpanel-import.body.properties.time.invalid |
docs |
properties.distinct_id |
required | Mixpanel documents `distinct_id` as required. An empty string is allowed for events that are not tied to a user. Placeholder values such as `null` or `0` are rejected. Body scope: []. Native JSON type: string or integer. Fix: Send the same `distinct_id` you use elsewhere for this user, or an empty string when there is no user. | vendor.mixpanel-import.body.properties.distinct_id.missingvendor.mixpanel-import.body.properties.distinct_id.invalid |
docs |
properties.$insert_id |
required | Mixpanel documents `$insert_id` as required so `/import` can be retried without double-counting. It must be at most 36 alphanumeric or hyphen characters. Body scope: []. Native JSON type: string. Fix: Send a unique id per event, at most 36 alphanumeric or hyphen characters. | vendor.mixpanel-import.body.properties.$insert_id.missingvendor.mixpanel-import.body.properties.$insert_id.emptyvendor.mixpanel-import.body.properties.$insert_id.invalid |
docs |
properties.ip |
optional | Mixpanel uses `ip` for GeoIP. Send a client address, or `0` to skip lookup. Do not hash it. Body scope: []. Native JSON type: string. Fix: Send the visitor IP, or `0` from a server. | vendor.mixpanel-import.body.properties.ip.emptyvendor.mixpanel-import.body.properties.ip.invalid |
docs |
properties.$current_url |
optional | It is the URL of the page on which the event was tracked. Mixpanel documents `$current_url` on the JavaScript SDK default-property table. Body scope: []. Native JSON type: string. Fix: Send an absolute URL in `properties.$current_url`, including the scheme. | vendor.mixpanel-import.body.properties.$current_url.emptyvendor.mixpanel-import.body.properties.$current_url.invalid |
docs |
properties.$referrer |
optional | It is the referring URL, including your own domain. Mixpanel documents `$referrer` on the JavaScript SDK default-property table. Body scope: []. Native JSON type: string. Fix: Send an absolute referring URL, or omit the field when there is no referrer. | vendor.mixpanel-import.body.properties.$referrer.emptyvendor.mixpanel-import.body.properties.$referrer.invalid |
docs |
properties.mp_lib |
optional | It names the Mixpanel library that sent the event, such as `web`, `android`, or `swift`. Mixpanel documents `mp_lib` on the SDK default-property table. Body scope: []. Native JSON type: string. Fix: Send `properties.mp_lib`, or drop the empty pair. | vendor.mixpanel-import.body.properties.mp_lib.emptyvendor.mixpanel-import.body.properties.mp_lib.invalid |
docs |
properties.$lib_version |
optional | It is the Mixpanel library version. Mixpanel documents `$lib_version` on the SDK default-property table. Body scope: []. Native JSON type: string. Fix: Send `properties.$lib_version`, or drop the empty pair. | vendor.mixpanel-import.body.properties.$lib_version.emptyvendor.mixpanel-import.body.properties.$lib_version.invalid |
docs |
properties.$device_id |
optional | It is the device-local Mixpanel ID. Mixpanel documents `$device_id` as regenerated by `reset()`. Body scope: []. Native JSON type: string. Fix: Send `properties.$device_id`, or drop the empty pair. | vendor.mixpanel-import.body.properties.$device_id.emptyvendor.mixpanel-import.body.properties.$device_id.invalid |
docs |
properties.$user_id |
optional | It is the identified user ID. Mixpanel documents `$user_id` as set by `identify()`. Body scope: []. Native JSON type: string. Fix: Send `properties.$user_id` after identify, or drop the empty pair. | vendor.mixpanel-import.body.properties.$user_id.emptyvendor.mixpanel-import.body.properties.$user_id.invalid |
docs |
properties.$screen_height |
optional | It is the device screen height in pixels, or points on iOS. Mixpanel documents `$screen_height` on the SDK default-property table. Body scope: []. Native JSON type: integer. Fix: Send `properties.$screen_height` as an integer pixel or point count. | vendor.mixpanel-import.body.properties.$screen_height.emptyvendor.mixpanel-import.body.properties.$screen_height.invalid |
docs |
properties.$screen_width |
optional | It is the device screen width in pixels, or points on iOS. Mixpanel documents `$screen_width` on the SDK default-property table. Body scope: []. Native JSON type: integer. Fix: Send `properties.$screen_width` as an integer pixel or point count. | vendor.mixpanel-import.body.properties.$screen_width.emptyvendor.mixpanel-import.body.properties.$screen_width.invalid |
docs |
properties.$city |
optional | It is the city Mixpanel parses from `ip`, or a city you set yourself. Mixpanel documents `$city` on the ingestion GeoIP table. Body scope: []. Native JSON type: string. Fix: Send `properties.$city`, or drop the empty pair. | vendor.mixpanel-import.body.properties.$city.emptyvendor.mixpanel-import.body.properties.$city.invalid |
docs |
properties.$region |
optional | It is the region Mixpanel parses from `ip`, or a region you set yourself. Mixpanel documents `$region` on the ingestion GeoIP table. Body scope: []. Native JSON type: string. Fix: Send `properties.$region`, or drop the empty pair. | vendor.mixpanel-import.body.properties.$region.emptyvendor.mixpanel-import.body.properties.$region.invalid |
docs |
properties.mp_country_code |
optional | It is the country Mixpanel parses from `ip`. Mixpanel documents a 2-letter country code. Body scope: []. Native JSON type: string. Fix: Send `properties.mp_country_code` as a two-letter code, such as `US`. | vendor.mixpanel-import.body.properties.mp_country_code.emptyvendor.mixpanel-import.body.properties.mp_country_code.invalid |
docs |
|
optional | The vendor documents `` in the request contract. Body scope: []. Native JSON type: object. | vendor.mixpanel-import.body..invalid |
docs |
body.placeholder_identifier |
required | The identifier is a placeholder Mixpanel rejects. `/import` disallows values such as `null`, `0`, `anonymous`, and the all-zero UUID. Body scope: []. Fix: Send a real `distinct_id` or `$insert_id`, or an empty `distinct_id` when there is no user. | vendor.mixpanel-import.body.placeholder_identifier |
docs |
body.hashed_plaintext_field |
required | `properties.ip` looks like a SHA-256 digest, but Mixpanel documents it as an IP address, or `0` to skip GeoIP. Body scope: []. Fix: Send the raw IP address, or `0`. | vendor.mixpanel-import.body.hashed_plaintext_field |
docs |
|
optional | Body scope: [].properties.**. Presence diagnostic severity: error. Value diagnostic severity: error. Native JSON type: string or number or boolean or object or array or null. Maximum array items: 254. Maximum object properties: 254. | vendor.mixpanel-import.body..invalid |
docs |
|
optional | Body scope: [].properties.**. Presence diagnostic severity: error. Value diagnostic severity: warning. Native JSON type: string or number or boolean or object or array or null. Maximum decoded UTF-8 bytes: 255. | vendor.mixpanel-import.body..invalid |
docs |
|
optional | Body scope: [].properties.*. Applies when {"kind":"json_type","param":"","json_type":"object"}. Presence diagnostic severity: error. Value diagnostic severity: error. Native JSON type: string or number or boolean or object or array or null. Maximum container depth: 3. | vendor.mixpanel-import.body..invalid |
docs |
|
optional | Body scope: [].properties.**[]. Applies when {"kind":"json_type","param":"","json_type":"object"}. Presence diagnostic severity: error. Value diagnostic severity: warning. Native JSON type: string or number or boolean or object or array or null. Maximum container depth: 1. | vendor.mixpanel-import.body..invalid |
docs |
method |
required | The Import API uses POST. Complete HTTP capture contract. Native JSON type: string. | vendor.mixpanel-import.http.method.missingvendor.mixpanel-import.http.method.emptyvendor.mixpanel-import.http.method.invalid |
docs |
content_type |
required | Import supports JSON arrays or newline-delimited JSON. Complete HTTP capture contract. Native JSON type: string. | vendor.mixpanel-import.http.content_type.missingvendor.mixpanel-import.http.content_type.emptyvendor.mixpanel-import.http.content_type.invalid |
docs |
body |
required | JSON and NDJSON normalize to the same event array. Complete HTTP capture contract. Native JSON type: array. Minimum array items: 1. | vendor.mixpanel-import.http.body.missingvendor.mixpanel-import.http.body.invalid |
docs |
headers.authorization |
required | Import requires its published Basic authentication header. Complete HTTP capture contract. Native JSON type: string. | vendor.mixpanel-import.http.headers.authorization.missingvendor.mixpanel-import.http.headers.authorization.emptyvendor.mixpanel-import.http.headers.authorization.invalid |
docs |
basic_auth |
required | Basic credentials must decode. Complete HTTP capture contract. Native JSON type: object. | vendor.mixpanel-import.http.basic_auth.missingvendor.mixpanel-import.http.basic_auth.invalid |
docs |
basic_auth.username |
required | Service-account username, project token or legacy secret. Complete HTTP capture contract. Native JSON type: string. | vendor.mixpanel-import.http.basic_auth.username.missingvendor.mixpanel-import.http.basic_auth.username.emptyvendor.mixpanel-import.http.basic_auth.username.invalid |
docs |
basic_auth.password |
optional | Empty for the project-token branch; populated for service accounts. Complete HTTP capture contract. Native JSON type: string. | vendor.mixpanel-import.http.basic_auth.password.emptyvendor.mixpanel-import.http.basic_auth.password.invalid |
docs |
query.project_id |
required | Project ID is required when a service-account password is supplied. Complete HTTP capture contract. Applies when {"kind":"value_pattern","param":"basic_auth.password","pattern":".+"}. Native JSON type: string. | vendor.mixpanel-import.http.query.project_id.missingvendor.mixpanel-import.http.query.project_id.emptyvendor.mixpanel-import.http.query.project_id.invalid |
docs |
Validate a payload
pixellint validate json @payload.json --rulepack vendor/mixpanel-import
Try this failing payload in the playground. Mixpanel import with a placeholder distinct_id.
[{"event":"Signup","properties":{"time":1618716477000,"distinct_id":"anonymous","$insert_id":"29fc2962-6d9c-455d-95ad-95b84f09b9e4"}}]
cargo install pixellint
·
npm install pixellint