Events

The track and identify wire APIs, and the property rules.

Track

POST {ingest_host}/analytics/events
X-VortexAuth-Key: <project_key>
Content-Type: application/json
{
  "event": "signup.completed",
  "external_user_id": "u-12345",
  "properties": { "plan": "pro" },
  "occurred_at": "2026-05-01T12:34:56.789Z"
}
FieldRequiredNotes
eventyesdot.case, e.g. signup.completed.
external_user_idyesA stable id your app owns: the signed-in user id, or a persistent anonymous id. Never blank, never per-request.
propertiesnoObject with snake_case keys.
occurred_atnoRFC 3339. The server stamps now when absent. Set it only when replaying history.

A 200 returns {"event_id": "<uuid>"}. A 4xx means the payload is malformed and retrying it unchanged will fail identically; a 5xx is worth retrying with backoff. The SDKs queue, persist, and retry for you.

Identify

POST {ingest_host}/analytics/identify
{ "alias_id": "<anonymous id>", "primary_id": "u-12345" }

Tells the server two ids are the same person. The SDKs call this from identify() using the anonymous id they minted before sign-in.

Reserved properties

Keys with a $ prefix belong to the SDK. $lib, $lib_version, and $session_id are stamped on every event; caller-supplied $ keys are dropped with a console warning.

Three plain keys have product meaning:

  • environment — stamped from the client's environment option. Reads (dashboard, MCP) can filter on it, so keep development traffic labelled.
  • signup_source — how this user arrived. When a user comes through a tracked link, the SDK stamps vx_link and attribution falls back to it.
  • plan — the user's plan, used by breakdowns and channel comparisons.

Naming

Use dot.case verbs in past tense: project.created, checkout.completed, trial.started. The dashboard's event annotations let you add display labels and hide internal events later, so pick names for the wire, not for the chart.