Events API

Record something that happened in your own app, such as a purchase or a signup, so an automation can react to it. Events are attached to a contact. All routes need a bearer API key (see API Overview).

Record an event

POST /api/v1/events
{
  "name": "order_placed",
  "email": "ada@example.com",
  "properties": { "order_id": "1042", "items": 3 },
  "value": 59.9,
  "currency": "USD",
  "externalId": "order-1042"
}
FieldNotes
nameRequired. See name rules below
emailThe contact's email. Provide email or contactId
contactIdThe contact's id. Used instead of email when both are given
propertiesOptional object. At most 50 keys and 8 KB when serialized
valueOptional money amount in major units (for example dollars). Stored as whole minor units, so 19.99 becomes 1999
valueCentsOptional money amount as a whole number of minor units. Wins over value if both are sent
currencyOptional three-letter code, stored uppercase. Anything else is ignored
externalIdOptional. Your own unique id for the event, used to make retries safe. Truncated to 200 characters

Event names

Names are normalized to lowercase snake_case and cut to 64 characters, so Order Placed, order-placed and orderPlaced all become order_placed. An automation trigger name is normalized the same way, so it still matches.

Contacts

  • With contactId, the contact must be in your workspace or you get 404.
  • With email, an existing contact is used. If there is none, a new contact is created with status PENDING, never SUBSCRIBED. An event is not a marketing opt-in. See Double Opt-In.

Retries

If you send an externalId that already exists in your workspace, nothing new is recorded and no automation runs again. You get 200 with { "id": "...", "duplicate": true, "createdAt": "..." }.

Response

A new event returns 201:

{ "data": { "id": "clx...", "name": "order_placed", "createdAt": "2026-10-04T12:00:00.000Z" } }

Recording the event also starts any live automation with a custom event trigger of that name for the contact, and passes the event to your lead scoring rules. If starting the automation fails, the event is still recorded and the request still succeeds.

Errors: 400 if the body is not valid JSON, 422 for a missing name, a missing email and contactId, an invalid email, bad properties, or a bad money value.

List events

GET /api/v1/events
QueryMeaning
limitPage size, default 20, maximum 100
afterCursor from the previous page
nameOnly events with exactly this stored name
contactIdOnly events for this contact

Items have id, name, properties, valueCents, currency, contactId and createdAt, newest first.

Because name is matched exactly, filter with the normalized form, for example order_placed.