API Reference
Every SDK talks to this endpoint under the hood. Use it directly only if you're integrating from a platform no SDK covers yet β otherwise prefer the JavaScript, Flutter, React Native, Swift, Kotlin, or Node.js SDK.
Ingest events
POST /api/v1/event
Body: a batch of one or more events.
{
"events": [
{
"sid": "YOUR_SITE_ID", // required β site_id from Integration Hub
"uid": "HASHED_USER_ID", // required β SHA-256 hash, never a raw id
"p": "/checkout", // required β URL path
"t": "pageview", // optional β event type, defaults to "pageview"
"ref": "https://google.com", // optional β referrer
"utm": { "source": "newsletter" }, // optional β UTM parameters
"meta": { "plan": "pro" } // optional β custom event properties
}
]
} | Field | Required | Notes |
|---|---|---|
sid | Yes | Site ID from the dashboard's Integration Hub. |
uid | No | SHA-256 hash of the visitor/user id β omitted entirely for anonymous visitors (no identify() call). Every SDK computes this client-side (or, for the Node.js SDK, server-side) β never send a raw user id, email, or name. |
p | Yes | URL path or screen name. |
t | No | Event type, e.g. pageview, signup_completed. |
ref | No | Referrer URL. |
utm | No | UTM campaign parameters, as a flat object. |
meta | No | Non-identifying custom event properties. |
Authentication
Web requests are authenticated by Origin β the domain
making the request must match what was registered for that Site ID in
the dashboard (localhost is always allowed outside
production).
Non-web requests (mobile, desktop, server) include the app's Secret Key, issued alongside the Site ID for non-web platforms.
Rate limits & resilience
The ingestion endpoint is rate-limited per site. Every SDK batches events (flushing periodically or on a size threshold) so transient network failures or rate-limit responses don't lose data β the SDKs' batching is the intended usage pattern, not per-event calls. Most SDKs also persist unsent events locally between flushes; the Node.js SDK queues in memory only (see its docs for why), and a tracking pixel has no queue at all β it's a single fire-and-forget request per load.