Public tracking
One endpoint, and it is not under /api. The browser beacon lives at POST /e
on purpose: content blockers match by pattern, and the patterns they ship are the
obvious words — track, collect, pixel, analytics. A one-character path on
your own domain is not on anybody's filter list.
It is unauthenticated in the usual sense: what identifies the caller is the site's
public write_key, which ships in your HTML, and what protects it is the domain
allow-list you configure in the CRM. An origin that is not on that list is refused
before the controller runs — fail closed, not fail open.
POST /e the beacon the tracking script fires
OPTIONS /e CORS preflight
You almost certainly do not want to call it by hand. The tracking script does it
for you, batches the events, and carries the visitor's anonymous_id — which is
the value that makes everything afterwards worth anything.
From your backend, not from a browser
For events your server knows about — a purchase, a refund, a subscription that
renewed — use POST /api/v1/events instead. It is in the reference under
Pixel · server events, and it authenticates with the site's secret
key rather than the public write key.
Send the anonymous_id your form received in its hidden kz_anonymous_id field
and the purchase joins up with the browsing that led to it. Without it the event
still lands, but as an orphan: no source, no session, nothing to explain where
the customer came from.
Rate limits
POST /api/v1/events is throttled by throttle:tracking — the budget is in the
introduction, and every response carries X-RateLimit-Remaining. The browser
beacon has its own per-site and per-visitor ceilings, configured in
config/tracking.php.