vendor/posthog · vendor documented
PostHog capture treats an epoch timestamp as now
You backfill six months of events. Insights show a spike today. The events are not missing. They are stamped with the time PostHog received them.
timestamp is ISO 8601. An epoch number is a different type. Capture still accepts the request. The historical value is not applied. Missing event or distinct_id is not ingested, and PostHog still returns 200 OK.
timestamp is ISO 8601, not epoch
Send 2026-07-26T06:00:00Z. Segment uses the same shape. Amplitude wants milliseconds. If your pipeline already emits epoch for Amplitude, do not reuse the field on PostHog.
Every event needs distinct_id
On a single capture and on every row of batch. PostHog's own docs: a missing name, a missing distinct_id, or an empty distinct_id is not ingested, and you still get 200.
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 |
|---|---|---|---|---|
api_key |
required | It is the project API key, and PostHog rejects the request without it. Fix: Send the project API key from your PostHog project settings. | vendor.posthog.body.api_key.missingvendor.posthog.body.api_key.empty |
docs |
event |
required | It is the name of the event being captured. Fix: Name the event, such as `user signed up`. | vendor.posthog.body.event.missingvendor.posthog.body.event.empty |
docs |
distinct_id |
required | It identifies the person the event belongs to. Fix: Send the same `distinct_id` you use elsewhere for this person. | vendor.posthog.body.distinct_id.missingvendor.posthog.body.distinct_id.empty |
docs |
timestamp |
optional | PostHog documents the timestamp as ISO 8601. An epoch number is read as the ingestion time instead. Fix: Send an ISO 8601 timestamp, such as `2026-07-26T06:00:00Z`. | vendor.posthog.body.timestamp.emptyvendor.posthog.body.timestamp.invalid |
docs |
Validate a payload
pixellint validate json @payload.json --rulepack vendor/posthog
Or paste it into the playground. Same engine, in the browser, nothing sent anywhere.
cargo install pixellint
·
npm install pixellint