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"
}
| Field | Notes |
|---|---|
name | Required. See name rules below |
email | The contact's email. Provide email or contactId |
contactId | The contact's id. Used instead of email when both are given |
properties | Optional object. At most 50 keys and 8 KB when serialized |
value | Optional money amount in major units (for example dollars). Stored as whole minor units, so 19.99 becomes 1999 |
valueCents | Optional money amount as a whole number of minor units. Wins over value if both are sent |
currency | Optional three-letter code, stored uppercase. Anything else is ignored |
externalId | Optional. 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 get404. - With
email, an existing contact is used. If there is none, a new contact is created with statusPENDING, neverSUBSCRIBED. 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
| Query | Meaning |
|---|---|
limit | Page size, default 20, maximum 100 |
after | Cursor from the previous page |
name | Only events with exactly this stored name |
contactId | Only 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.