Skip to main content
An event is something a person or object did at a point in time: a 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).
Subjects are referenced by your external ids. They’re stored as-is and Boom resolves the internal link best-effort: recording an event for a person who hasn’t synced yet still succeeds, and the link is back-stitched later. A missing subject never fails the request.

Record an event

Returns { "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 the externalId you supplied:
Or list them, newest first, with optional filters (combined with AND):
Filters match the external references you supplied at ingest, so events recorded before their subject synced are still returned.

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 carries next_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.

Quickstart

Record your first event alongside people and objects.

Relationship types

Model the links between the people and objects your events reference.