Validation here is forgiving on purpose: an invalid event is dropped from a batch, never a reason to fail it. That is the right trade for analytics, where losing one event matters far less than losing the request that produced it, but it means a misconfigured client gets 204 and no data. This page is the list of everything that can be dropped, so you can find out which one you hit.
Numbers verified 2026-09-28 against the running service.
Batch and request ceilings
Beyond the event ceiling, the surplus is counted, not queued. On /v1/ingest the extra events are dropped; on /v1/import they come back in rejected. The service slices your list into batches of 50 internally, so you do not have to chunk for /v1/import, only for /v1/ingest.
Rate limits and quota
Over the per-key limit: 429 {"error":"rate_limited"}. The bucket is per key, so a whole fleet sharing one Server key shares one bucket. If you need more headroom, create more keys rather than asking for a higher number: keys are free and a separate key per service also tells you which service is noisy.
Over the Project's monthly quota: 429 {"error":"quota_exceeded"}. See Usage and billing.
Event names
The rule, exactly: 1 to 96 characters from letters, digits, _, $, ., : and -, with interior spaces allowed and no leading or trailing space.
A name the validator rejects means the whole event is dropped. The Mixpanel shim is gentler: it replaces rejected characters with _ and cuts the name at 96, so an SDK's event is never lost to a stray character.
Names are case-sensitive and never normalised.
Ids
At least one of did, uid, aid must survive, or the event is dropped. This is the most common cause of a 204 with nothing to show for it.
Properties
Values must be scalars: string, finite number, boolean or null. An array or a nested object is dropped on /v1/ingest. The keys __proto__, constructor and prototype are refused.
NaN and Infinity are not finite, so they are dropped. A number arriving as a string stays a string, and a report that sums it will not.
The Mixpanel shim is again gentler: it keeps arrays and nested objects as compact JSON strings rather than dropping them, cut at 512 characters.
Timestamps
/v1/import keeps every event's ts exactly as sent; the service marks imported ids internally so they are never clamped. Use your own stable id per row (an order id, a row key) so a re-run after a failure is idempotent. Only /v1/ingest clamps timestamps to the last 24 hours.
Clamping is not an error and is not reported. Verify a backfill by looking at the earliest event in a report, not at the import's answer.
Element metadata
Autocaptured events carry el. Every field has a cap, and a value over its cap drops the whole el object while keeping the event: tag 32, selector 512, text 64, href 512, data-track 96, id 128, at most 8 classes of 64 characters each, field name 96. el never contains an input's value.
Sessions and profiles
- Session properties (
sp): known keys (utm_source,utm_medium,utm_campaign,utm_term,utm_content, referrer, landing path) become columns; the rest are kept as properties. First-touch columns are written once and not overwritten. profileon a$profileevent is honoured only from a Server key. From anyone else it is ignored, and the event still stores.- Group keys per Project: 10. Allowed origins per Project: 50. Blocked IP hashes per Project: 500.
Retention
Default retention is the service default; a Project can set retentionDays between 1 and 3 650. See Data and privacy.
Concurrency
GET /v1/live allows 50 concurrent subscribers per Project. Over that: 503 {"error":"live_subscribers_exhausted","limit":50}. The stream buffers nothing, so a subscriber sees only what arrives after it connects.
Debugging a silent drop
A 204 and nothing in the Live view, in the order worth checking:
- No identifier. No
did,uidoraidsurvived. A Project token'sdidis always stripped, so a browser client that sends onlydidsends nothing usable. - Duplicate
id. The same id twice in one batch, or an id already stored. Common when a client reuses one id for a whole batch. - Rejected name. A character outside the allowed set, a leading space, or over 96 characters.
- Empty batch.
eventsmissing, not an array, orvnot1. A204is also the answer when a batch validates down to zero events. - Wrong Project. The credential decides the Project, and a
x-analytics-projectheader cannot override it. Check which Project the key belongs to. - Origin pinned. If the Project lists allowed origins, a browser request from another Origin is refused outright.
If the event does reach the Live view but is missing from a report, the ingest side is fine: look at the report's date range, its filters, and whether it depends on a defined event whose rules do not match.