DataVisitors never drops an event silently. A batch that is read at all comes back 202 with a per-event answer; a request that cannot be read at all comes back with a status that says why.
The answer to a batch
HTTP/1.1 202 Accepted{ "accepted": 2, "rejected": [ { "index": 1, "code": "bad_event_name" } ]}
index is the event's position in the array you sent, so you can match a refusal to the event that caused it without guessing.
Per-event codes
The event was malformed.
| Code | What it means |
|---|---|
bad_event_id |
The event_id is not a ULID or UUIDv7. |
bad_event_name |
The name fails [a-z][a-z0-9_]{0,63}. |
reserved_event_name |
The name begins sg_, which belongs to the platform. |
bad_occurred_at |
The time is more than 7 days in the past or 10 minutes in the future. |
bad_properties |
The properties break a count, depth or size rule. |
event_too_large |
The single event is over 32 KB. |
The identity or the consent did not add up.
| Code | What it means |
|---|---|
bad_identity |
An id fails ^[A-Za-z0-9_-]{8,64}$, or ids were sent on a stateless event, which must carry none. |
bad_consent |
The consent value is not stateless, anonymous or identified. |
consent_pending |
A pending event was sent. It is refused on purpose, so a misconfigured SDK fails loudly instead of storing data without resolved consent. |
bad_traits |
Traits on the wrong event, without identified consent or a valid user_id, or failing the traits shape. |
traits_limit |
The project's person cap, or the stored profile's own caps, refused the merge. |
origin_locked_key |
sg_identify carrying traits arrived on a browser key that is locked to origins. Send traits from a server key. |
The project said no. These are your own rules — see Shields and Allowed origins.
| Code | What it means |
|---|---|
hostname_not_allowed |
The browser's host is not on the project's allowed hostnames. |
blocked_country |
The visitor's country is on the project's blocked list. |
blocked_path |
The page path matches a blocked path. |
hosting_network |
The address belongs to a compute cloud and the hosting-network shield is on. Browser requests only. |
vitals_off |
A Web Vitals beacon for a project that has not opted in. The server enforces the choice whatever the tag says. |
custom_events_not_in_plan |
The workspace's plan does not include custom events. Refused per event, so a page view in the same batch is still recorded. |
Nobody was reading, or we already have it.
| Code | What it means |
|---|---|
bot |
The user agent classifies as a crawler, a script or a headless browser. |
spam_referrer |
The referrer host is on Matomo's referrer-spam list, or under a host that is. |
prefetch |
The request came from a prerendering or prefetching page. |
duplicate |
This event_id has already been accepted. Retrying a batch is safe; this is what makes it safe. |
bad_vitals |
The vitals field is on the wrong event, or sg_vitals arrived without it. |
Statuses that refuse the whole request
| Status | Meaning | Retry? |
|---|---|---|
400 |
The batch could not be read, carried trailing data, or broke an envelope rule. | No — fix it. |
401 |
The key is unknown, revoked or expired. | No. |
403 |
The key's origin rules refuse this request. | No. |
405 |
Something other than POST. |
No. |
429 |
You are sending too fast. | Yes, after a pause. |
500 |
Configuration was briefly unavailable. | Yes. |
503 |
Storage was briefly unavailable and nothing was written. | Yes. |
What to retry, and how
Retry 429, 500 and 503. Back off a little further on each attempt, and keep the same event_id on every event so the second delivery is de-duplicated rather than double-counted.
A 403 and a 429 are counted against the project, as whole requests, and shown under Tracking → Ignored traffic — so a key locked to the wrong website shows up as a number rather than as a flat line. A 401 is not: a key that is unknown, revoked or belongs to a deleted project cannot be told which project it was meant for.
Do not retry 400, 401, 403 or 405: the same request will be refused the same way. Nor a per-event code inside a 202 — the rest of that batch was accepted, and the refused event needs changing, not resending.