Events API
Fire custom named events against contacts to trigger behavior-driven automations. This is the most flexible way to connect your application's business logic to EmailSendX's automation engine.
Overview
The Events API lets you send named events from your application to EmailSendX. When an event is fired for a contact, EmailSendX checks all active automations in the workspace for ones that have a Custom Event trigger configured with a matching event name. All matching automations are triggered immediately for that contact.
This creates a direct bridge between your application's business events (checkout completed, trial started, invoice paid) and targeted email workflows in EmailSendX.
Typical event-to-automation flow:
- User completes checkout in your app
- Your backend calls
POST /contacts/{id}/eventswithname: "purchase_completed" - EmailSendX matches all active automations with trigger
CUSTOM_EVENT: purchase_completed - Matching automations start running for the contact — sending welcome emails, onboarding sequences, etc.
Fire an Event
/api/v1/contacts/{id}/eventsscope: contacts:writeFire a named custom event for a contact. Returns the count of automations that were triggered by the event.
Parameters
| Name | Type | In | Required | Description |
|---|---|---|---|---|
| id | string | path | required | The contact ID to fire the event for |
| name | string | body | required | Event name. Case-insensitive match against automation trigger configuration. |
| data | object | body | optional | Free-form JSON data payload attached to this event. Available in automation conditional steps. |
Request Body
{
"name": "purchase_completed",
"data": {
"orderId": "ord_abc123",
"amount": 99.00,
"currency": "USD",
"items": ["Pro Plan - Annual"],
"coupon": "LAUNCH20"
}
}Response
{
"data": {
"contactId": "clx1a2b3c4d5e6f7g8h9i0j",
"eventName": "purchase_completed",
"matchingAutomations": 2,
"firedAt": "2026-04-22T09:15:30Z"
}
}Automation Matching
When an event is fired, EmailSendX finds all automations in the workspace where:
- The automation's trigger type is
CUSTOM_EVENT - The trigger's configured event name matches the fired event name (case-insensitive)
- The automation's status is
active
All matching automations are triggered in parallel. The matchingAutomations field in the response tells you how many were triggered.
Case-insensitive matching
purchase_completed, Purchase_Completed, and PURCHASE_COMPLETED all match an automation configured with the event name purchase_completed. Use a consistent naming convention for clarity.# Response when 0 automations matched
{
"data": {
"contactId": "clx1a2b3c4d5e6f7g8h9i0j",
"eventName": "trial_started",
"matchingAutomations": 0,
"firedAt": "2026-04-22T09:16:00Z"
}
}
# Note: matchingAutomations: 0 is not an error.
# It means no active automations are configured for this event name.Data Payload
The optional data field lets you pass arbitrary JSON to the automation runner. This data is available within automation conditional steps, allowing you to branch logic based on event properties.
For example, a purchase_completed event with data.amount could branch the automation to send different emails based on purchase value.
Data payload limits:
- Maximum payload size: 16 KB
- Must be a valid JSON object (not an array or primitive)
- Nested objects and arrays are supported
Complete Example: Purchase Flow
A realistic backend integration that upserts a contact, fires a purchase event, and enrolls them in a post-purchase automation:
const API_KEY = process.env.EMAILSENDX_API_KEY;
const BASE = 'https://emailsendx.com/api/v1';
async function handleCheckoutCompleted(order) {
const headers = {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
};
// 1. Upsert the contact
const upsertRes = await fetch(`${BASE}/contacts`, {
method: 'POST',
headers,
body: JSON.stringify({
email: order.customerEmail,
firstName: order.customerFirstName,
metadata: {
plan: order.planName,
customerId: order.stripeCustomerId,
},
}),
});
const { data: contact } = await upsertRes.json();
// 2. Fire the purchase_completed event
const eventRes = await fetch(`${BASE}/contacts/${contact.id}/events`, {
method: 'POST',
headers,
body: JSON.stringify({
name: 'purchase_completed',
data: {
orderId: order.id,
amount: order.totalAmount,
currency: order.currency,
items: order.lineItems.map(i => i.name),
},
}),
});
const { data: event } = await eventRes.json();
console.log(`Triggered ${event.matchingAutomations} automation(s)`);
}Events powering your automations?
Set up CUSTOM_EVENT automations in the dashboard to respond to every event your backend fires.