Events
| Method | Path | Scope | SDK |
|---|---|---|---|
POST | /api/v1/events | sequences:write | events.track |
One call does four things: upserts the contact, enrolls them into every active
sequence whose trigger equals type, re-arms flows waiting on that event, and
cancels their enrollments in the sequences you list under exitSequences.
Request
| Field | Type | Notes |
|---|---|---|
type | string | Required. Your event name, e.g. order.placed. Matched against each sequence's trigger. |
email | string | Required unless contactId is given; upserted if unknown. |
contactId | uuid | Address an existing contact instead. |
data | object | Event payload. Available to templates and branch conditions. |
exitSequences | string[] | Sequence keys to cancel active enrollments in. |
For a retryable business transition, send a stable Idempotency-Key header.
The key is scoped to the project and may be at most 200 characters.
curl -X POST https://mailroom.example.com/api/v1/events \
-H "Authorization: Bearer pk_live_…" \
-H "Idempotency-Key: order:ord_123:placed" \
-H "Content-Type: application/json" \
-d '{
"type": "order.placed",
"email": "ada@example.com",
"data": { "orderId": "ord_123", "total": 4200, "currency": "USD" },
"exitSequences": ["abandoned-cart"]
}'
Response
{
"ok": true,
"contactId": "9f0c…",
"enrolled": 1,
"reArmed": 0,
"exited": 1,
"duplicate": false
}
Counts, not ids:
enrolled— new enrollments started by this event.reArmed— waiting enrollments that this event advanced.exited— enrollments cancelled viaexitSequences.duplicate— this idempotency key completed previously; no lifecycle work was repeated.
All zeros is a normal outcome: it means no active sequence is triggered by that
type. The contact upsert still happened.
Errors
| Status | code | Cause |
|---|---|---|
| 409 | idempotency_in_progress | Another request currently holds this key; retry later |
| 422 | invalid_request | Missing type, or neither email nor contactId |
| 422 | reason string | The event could not be applied (e.g. the contact is unsubscribed) |
| 403 | forbidden | Key lacks sequences:write |
Notes
- Event names are free-form. Nothing validates
type, so a typo silently triggers nothing — keep the string in one constant on your side. - Not idempotent by nature. Two identical calls can create two enrollments where
re-entry allows it. A stable
Idempotency-Keyrecords the first completed transition and makes later replays no-ops. Concurrent duplicates receive 409 while the first request owns a ten-minute crash-recoverable lease. - Events are not analytics. Mailroom keeps them to drive automation, not to be queried back; there is no event-read endpoint.