payment_made, a checkout_started, a loan_disbursed. Unlike people and
custom objects (which you upsert to a current state), events are an
append-only log: each one is recorded once and read back later, individually
or as a filtered, paginated stream.
Anatomy of an event
At least one subject is required:
personExternalId, or the
customObjectType + customObjectExternalId pair. You may set both (a
person event about an object).Record an event
{ "created": true, "eventId": "evt_db_1", "externalId": "evt_123" }.
externalId is your own id echoed back. Keep it: it’s the key the
journey webhooks report as trigger.externalId, so you can match an
arriving journey_run.started / journey_run.ended to the record that caused it
without storing eventId.
For historical loads, Record events in bulk accepts up to 1000 per request.
Bulk ingest is treated as backfill: it does not fire journey enrollment,
so use the single endpoint for real-time, journey-triggering events.
Read events back
Fetch one by theexternalId you supplied:
Count events
To answer “how many”, ask for a count rather than paging the list and tallying it — a page is capped, so counting one gives you a number that looks right and is wrong.total counts events; unique_people counts people. They differ
whenever someone fires the same event more than once, so don’t report one as the
other. group_by buckets by a payload property, and events that don’t carry it
land under "value": null. You can narrow first with start/end,
personExternalId, or a filter on the payload
(&filter={"currency":"MXN"}).
If more distinct values exist than we return, groups_truncated is true — the
bucket counts then don’t add up to total.
One caveat worth reading twice: the unique_people inside each bucket never
add up to the top-level unique_people. Somebody who paid once with BBVA and
once with HSBC is a real person in both buckets. The counts split your events
into groups; the unique_people don’t split your people.
This counts one event name. To relate two different events — how many people
who did X went on to do Y — build a segment with event predicates instead.
Pagination
Every list endpoint (events, people, custom objects) is cursor-paginated. A response carriesnext_cursor; pass it back as ?cursor= to get the next
page, and loop until next_cursor is null:
limit defaults to 100 (max 1000). The cursor is opaque and stable under
concurrent writes: no skipped or duplicated rows.
Related
Quickstart
Record your first event alongside people and objects.
Relationship types
Model the links between the people and objects your events reference.