Skip to main content
Track events power more than campaigns and journeys. They feed the Customer-360 workspace timeline, where one snapshot call aggregates a contact’s events, conversations, voice calls, tickets, and more into a single workspace view.

Worked sequences

The four operations below are a complete walk-through of the Events surface, in the order an integration typically uses them: page through history, look up a single event, tail the live stream, and publish your own events. Every response below is a worked copy of the wire shape, and the Node examples route through the SDK’s orbit.request() helper.

List event history — GET /events

Page through the tenant’s recent-event history newest-first. The first request omits cursor; each page’s meta.pagination.cursor feeds the next request while has_more is true. Step 1 — first page
Node.js
Response (first page)
Step 2 — page forward while has_more is true
Node.js
Send the cursor verbatim — it is the id of the last event from the prior page (<ms>-<seq> form). When has_more comes back false, history is exhausted.

Get event details — GET /events/:id

Fetch one event by its id — either the canonical stream id from a list page (1755008400000-0) or a legacy publisher-minted evt_* id. Both resolve against the same history window. Request
Response
An id outside the retained history window returns a 404 with the NOT_FOUND error envelope.

Live tail — GET /events/stream (SSE)

For a live dashboard, open a Server-Sent Events connection instead of polling. The stream replays anything buffered after your Last-Event-ID (or ?lastEventId=), then tails events as they publish. A 30-second : heartbeat comment frame keeps the connection open between events. curl (server-side, secret API key)
Browser EventSource (Clerk session cookie)
Non-browser Node clients can keep a durable cursor on the ?lastEventId= query parameter (EventSource re-sends it as the Last-Event-ID header automatically). Sample stream frames
Each frame is id:, event:, and data: separated by a blank line. On reconnect, re-send the last id you saw and the replay pass fills the gap before the live tail resumes. ?types= narrows both the replay and the live tail to the comma-separated event types.

Publish a tracked event — POST /events/track

Record a domain event for a contact — Order Placed, Subscription Renewed, Trial Converted — to drive lifecycle campaigns, journey triggers, and the customer-360 timeline. The body is validated against the same per-event contract the schema registry publishes; GET /events/schema-registry returns that catalog (dialect, per-type JSON Schema, example payload, and a drift-detecting fingerprint) so you can pin the shape client-side. Request
Response
event is required; contact_email or contact_phone identify the contact (unmatched events are still recorded and stitch later). properties carries event attributes, message_id is a client-side dedup key, and timestamp is the client event time — the server’s receipt time remains the canonical sort key. A retry with the same Idempotency-Key or message_id returns deduped: true without writing a second row. The registry is fetched with a plain GET:
Node.js
Poll data.catalog_version to detect any change to the platform event contract cheaply, then diff each schema’s fingerprint to see which event types moved.