Event Payloads Reference¶
This document provides comprehensive documentation for all event payloads that trigger compute functions in Centrali.
Table of Contents¶
- Overview
- Accessing Event Data
- Event Types
- Payload Structures
- record_created
- records_bulk_created
- record_updated
- record_deleted
- record_restored
- record_reverted
- Failed Events
- Event Differences Table
- Common Patterns
Overview¶
When a record event occurs in Centrali, the system publishes an event payload containing all relevant information about the change. If you have an event-driven trigger configured for that event type and structure, your compute function will receive this payload.
Event Flow¶
Record Operation (create/update/delete)
↓
Event Published to NATS
↓
Orchestrator Matches Triggers
↓
Your Function Receives Event Payload
Accessing Event Data¶
Event data is available in your function through the executionParams global variable. Static configuration from your trigger is available in triggerParams.
executionParams vs triggerParams¶
| Variable | Contains | Set By |
|---|---|---|
executionParams | Dynamic event data | System (from the event) |
triggerParams | Static configuration | You (in trigger metadata) |
Example: Accessing Event Data¶
async function run() {
// Event data from the record operation
const event = executionParams.event; // "record_created"
const workspaceSlug = executionParams.workspaceSlug;
const recordSlug = executionParams.recordSlug; // Structure slug
const recordId = executionParams.recordId;
const data = executionParams.data; // Record data
const timestamp = executionParams.timestamp;
// Static config from trigger creation
const emailTemplate = triggerParams.emailTemplate;
const notifyAdmin = triggerParams.notifyAdmin;
api.log({
message: `Processing ${event}`,
recordId,
structure: recordSlug
});
return { success: true };
}
Event Types¶
Centrali supports the following record events:
| Event | Description | Trigger Condition |
|---|---|---|
record_created | New record created | After successful record creation |
records_bulk_created | Multiple records created in bulk | After successful bulk creation |
record_updated | Record modified | After successful record update |
record_deleted | Record deleted | After successful deletion (soft or hard) |
record_restored | Deleted record restored | After restoring a soft-deleted record |
record_reverted | Record reverted to previous version | After version rollback |
record_created_failed | Record creation failed | When create operation fails |
records_bulk_created_failed | Bulk record creation failed | When bulk create operation fails |
record_updated_failed | Record update failed | When update operation fails |
record_deleted_failed | Record deletion failed | When delete operation fails |
Payload Structures¶
record_created¶
Triggered when a new record is successfully created.
Payload Structure:
{
event: "record_created",
workspaceSlug: string, // Your workspace identifier
recordSlug: string, // Structure slug (e.g., "orders", "customers")
recordId: string, // UUID of the created record
data: {
id: string, // Record UUID
workspaceSlug: string, // Workspace identifier
recordSlug: string, // Structure slug
data: { // Your record fields
[fieldName: string]: any
},
status: "active", // Record status
version: 1, // Always 1 for new records
createdAt: string, // ISO 8601 timestamp
updatedAt: string, // ISO 8601 timestamp
createdBy: string, // User ID who created the record
updatedBy: string // User ID who created the record
},
timestamp: string, // ISO 8601 timestamp of the event
createdBy: string // User ID who created the record
}
Real Example:
// executionParams for a new order
{
event: "record_created",
workspaceSlug: "acme-corp",
recordSlug: "orders",
recordId: "550e8400-e29b-41d4-a716-446655440000",
data: {
id: "550e8400-e29b-41d4-a716-446655440000",
workspaceSlug: "acme-corp",
recordSlug: "orders",
data: {
orderNumber: "ORD-2025-001",
customerId: "cust_abc123",
items: [
{ productId: "prod_123", quantity: 2, price: 29.99 },
{ productId: "prod_456", quantity: 1, price: 49.99 }
],
status: "pending",
total: 109.97,
shippingAddress: {
street: "123 Main St",
city: "New York",
zip: "10001"
}
},
status: "active",
version: 1,
createdAt: "2025-01-15T10:30:00.000Z",
updatedAt: "2025-01-15T10:30:00.000Z",
createdBy: "user_xyz789",
updatedBy: "user_xyz789"
},
timestamp: "2025-01-15T10:30:00.123Z",
createdBy: "user_xyz789"
}
Function Example:
async function run() {
const { recordId, data, recordSlug } = executionParams;
// Access record fields
const orderNumber = data.data.orderNumber;
const customerId = data.data.customerId;
const total = data.data.total;
api.log({
message: "New order received",
orderNumber,
total
});
// Send notification
await api.http.post("https://api.example.com/notify", {
type: "new_order",
orderId: recordId,
orderNumber,
total
});
return { success: true, orderNumber };
}
records_bulk_created¶
Triggered when multiple records are created in a single bulk operation. Unlike record_created, this event contains only record IDs, not the full record data. This is for performance reasons - bulk operations can create thousands of records.
Payload Structure:
{
event: "records_bulk_created",
workspaceSlug: string, // Your workspace identifier
recordSlug: string, // Structure slug (e.g., "orders", "customers")
structureId: string, // UUID of the structure
recordIds: string[], // Array of created record UUIDs
count: number, // Number of records created
timestamp: string, // ISO 8601 timestamp of the event
createdBy: string, // User ID who created the records
schemaDiscoveryMode: string // "strict" | "schemaless" | "auto-evolving"
}
Real Example:
// executionParams for bulk order creation
{
event: "records_bulk_created",
workspaceSlug: "acme-corp",
recordSlug: "orders",
structureId: "123e4567-e89b-12d3-a456-426614174000",
recordIds: [
"550e8400-e29b-41d4-a716-446655440001",
"550e8400-e29b-41d4-a716-446655440002",
"550e8400-e29b-41d4-a716-446655440003"
],
count: 3,
timestamp: "2025-01-15T10:30:00.123Z",
createdBy: "user_xyz789",
schemaDiscoveryMode: "strict"
}
Function Example:
async function run() {
const { recordIds, count, recordSlug, workspaceSlug } = executionParams;
api.log({
message: "Bulk records created",
structure: recordSlug,
count,
recordIds: recordIds.slice(0, 5) // Log first 5 IDs
});
// Optionally fetch full records if needed
// Note: For large batches, consider processing asynchronously
if (count <= 100) {
const records = await api.centrali.getRecordsByIds(recordSlug, recordIds);
// Process records...
}
// Send summary notification
await api.http.post("https://api.example.com/notify", {
type: "bulk_import_complete",
structure: recordSlug,
count,
timestamp: executionParams.timestamp
});
return { success: true, processedCount: count };
}
Important Notes: - Bulk events do NOT contain full record data - only IDs - Use api.centrali.getRecordsByIds() if you need full record data - Consider batch processing for large imports to avoid timeouts - Single record_created events are NOT fired for bulk operations
record_updated¶
Triggered when an existing record is modified. Includes both the previous and current state.
Payload Structure:
{
event: "record_updated",
workspaceSlug: string,
recordSlug: string,
recordId: string,
data: {
before: { // Record BEFORE the update
id: string,
workspaceSlug: string,
recordSlug: string,
data: { [fieldName: string]: any },
status: string,
version: number, // Previous version number
createdAt: string,
updatedAt: string, // Previous update timestamp
createdBy: string,
updatedBy: string // Previous updater
},
after: { // Record AFTER the update
id: string,
workspaceSlug: string,
recordSlug: string,
data: { [fieldName: string]: any },
status: string,
version: number, // Incremented version
createdAt: string,
updatedAt: string, // New update timestamp
createdBy: string,
updatedBy: string // Current updater
}
},
timestamp: string,
updatedBy: string
}
Real Example:
// executionParams for an order status change
{
event: "record_updated",
workspaceSlug: "acme-corp",
recordSlug: "orders",
recordId: "550e8400-e29b-41d4-a716-446655440000",
data: {
before: {
id: "550e8400-e29b-41d4-a716-446655440000",
workspaceSlug: "acme-corp",
recordSlug: "orders",
data: {
orderNumber: "ORD-2025-001",
status: "pending",
total: 109.97,
shippingAddress: { street: "123 Main St", city: "New York", zip: "10001" }
},
status: "active",
version: 1,
createdAt: "2025-01-15T10:30:00.000Z",
updatedAt: "2025-01-15T10:30:00.000Z",
createdBy: "user_xyz789",
updatedBy: "user_xyz789"
},
after: {
id: "550e8400-e29b-41d4-a716-446655440000",
workspaceSlug: "acme-corp",
recordSlug: "orders",
data: {
orderNumber: "ORD-2025-001",
status: "shipped",
total: 109.97,
trackingNumber: "1Z999AA10123456784",
shippingAddress: { street: "123 Main St", city: "New York", zip: "10001" }
},
status: "active",
version: 2,
createdAt: "2025-01-15T10:30:00.000Z",
updatedAt: "2025-01-15T14:45:00.000Z",
createdBy: "user_xyz789",
updatedBy: "user_admin001"
}
},
timestamp: "2025-01-15T14:45:00.456Z",
updatedBy: "user_admin001"
}
Function Example - Detecting Changes:
async function run() {
const { recordId, data } = executionParams;
const { before, after } = data;
// Compare before and after to find changes
const previousStatus = before.data.status;
const newStatus = after.data.status;
if (previousStatus !== newStatus) {
api.log({
message: "Order status changed",
orderId: recordId,
from: previousStatus,
to: newStatus
});
// Send notification only when status changes to "shipped"
if (newStatus === "shipped" && before.data.status !== "shipped") {
const trackingNumber = after.data.trackingNumber;
await api.http.post("https://api.example.com/notify-customer", {
type: "order_shipped",
orderId: recordId,
trackingNumber,
email: after.data.customerEmail
});
}
}
return { success: true, statusChanged: previousStatus !== newStatus };
}
Function Example - Finding Changed Fields:
async function run() {
const { data } = executionParams;
const { before, after } = data;
// Find which fields changed
const changedFields = [];
for (const key in after.data) {
if (JSON.stringify(before.data[key]) !== JSON.stringify(after.data[key])) {
changedFields.push({
field: key,
from: before.data[key],
to: after.data[key]
});
}
}
api.log({
message: "Fields changed",
changes: changedFields
});
return { changedFields };
}
record_deleted¶
Triggered when a record is deleted (soft delete or hard delete).
Payload Structure:
{
event: "record_deleted",
workspaceSlug: string,
recordSlug: string,
recordId: string,
data: { // Complete record as it existed before deletion
id: string,
workspaceSlug: string,
recordSlug: string,
data: { [fieldName: string]: any },
status: string, // Status before deletion
version: number,
createdAt: string,
updatedAt: string,
createdBy: string,
updatedBy: string
},
timestamp: string,
deletedBy: string // User who deleted the record
}
Real Example:
// executionParams for a deleted order
{
event: "record_deleted",
workspaceSlug: "acme-corp",
recordSlug: "orders",
recordId: "550e8400-e29b-41d4-a716-446655440000",
data: {
id: "550e8400-e29b-41d4-a716-446655440000",
workspaceSlug: "acme-corp",
recordSlug: "orders",
data: {
orderNumber: "ORD-2025-001",
status: "cancelled",
total: 109.97,
cancellationReason: "Customer requested"
},
status: "active",
version: 3,
createdAt: "2025-01-15T10:30:00.000Z",
updatedAt: "2025-01-15T16:00:00.000Z",
createdBy: "user_xyz789",
updatedBy: "user_admin001"
},
timestamp: "2025-01-15T16:30:00.789Z",
deletedBy: "user_admin001"
}
Function Example:
async function run() {
const { recordId, data, deletedBy } = executionParams;
// Archive deleted record to external system
await api.http.post("https://api.example.com/archive", {
type: "deleted_order",
originalId: recordId,
orderNumber: data.data.orderNumber,
deletedBy,
archivedData: data.data,
deletedAt: executionParams.timestamp
});
api.log({
message: "Order archived after deletion",
orderNumber: data.data.orderNumber,
deletedBy
});
return { success: true, archived: true };
}
record_restored¶
Triggered when a soft-deleted record is restored.
Payload Structure:
{
event: "record_restored",
workspaceSlug: string,
recordSlug: string,
recordId: string,
data: {
before: { // Record in deleted/archived state
id: string,
workspaceSlug: string,
recordSlug: string,
data: { [fieldName: string]: any },
status: "archived", // Was archived/deleted
version: number,
createdAt: string,
updatedAt: string,
createdBy: string,
updatedBy: string
},
after: { // Record after restoration
id: string,
workspaceSlug: string,
recordSlug: string,
data: { [fieldName: string]: any },
status: "active", // Now active again
version: number, // Version incremented
createdAt: string,
updatedAt: string, // Updated to restoration time
createdBy: string,
updatedBy: string // User who restored
}
},
timestamp: string,
restoredBy: string
}
Function Example:
async function run() {
const { recordId, data, restoredBy } = executionParams;
const { before, after } = data;
api.log({
message: "Record restored",
recordId,
restoredBy,
previousStatus: before.status,
newStatus: after.status
});
// Re-sync restored record with external system
await api.http.post("https://api.example.com/sync", {
action: "restore",
recordId,
data: after.data
});
return { success: true };
}
record_reverted¶
Triggered when a record is reverted to a previous version.
Payload Structure:
{
event: "record_reverted",
workspaceSlug: string,
recordSlug: string,
recordId: string,
data: {
before: { // Record before revert
id: string,
data: { [fieldName: string]: any },
version: number, // Higher version number
// ... other fields
},
after: { // Record after revert (restored to older version's data)
id: string,
data: { [fieldName: string]: any },
version: number, // New version (incremented, not the old version number)
// ... other fields
}
},
timestamp: string,
revertedBy: string,
revertedToVersion: number // The version number that was restored
}
Function Example:
async function run() {
const { recordId, data, revertedBy } = executionParams;
const { before, after } = data;
api.log({
message: "Record reverted to previous version",
recordId,
revertedBy,
fromVersion: before.version,
toVersion: after.version
});
return { success: true };
}
Failed Events¶
Failed events are triggered when a record operation fails. They include the error information.
record_created_failed¶
{
event: "record_created_failed",
workspaceSlug: string,
recordSlug: string,
data: { [fieldName: string]: any }, // Data that was attempted to be created
timestamp: string,
createdBy: string,
error: string // Error message
}
records_bulk_created_failed¶
{
event: "records_bulk_created_failed",
workspaceSlug: string,
recordSlug: string,
count: number, // Number of records that were attempted
timestamp: string,
createdBy: string,
error: string // Error message
}
record_updated_failed¶
{
event: "record_updated_failed",
workspaceSlug: string,
recordSlug: string,
recordId: string,
data: { [fieldName: string]: any }, // Data that was attempted
timestamp: string,
updatedBy: string,
error: string // Error message
}
record_deleted_failed¶
{
event: "record_deleted_failed",
workspaceSlug: string,
recordSlug: string,
recordId: string,
timestamp: string,
deletedBy: string,
error: string // Error message
}
Function Example - Handling Failed Events:
async function run() {
const { event, recordSlug, error, timestamp } = executionParams;
// Log failure to monitoring system
await api.http.post("https://api.example.com/alerts", {
type: "operation_failed",
event,
structure: recordSlug,
error,
timestamp,
severity: "warning"
});
api.logError({
message: `${event} failed`,
error,
structure: recordSlug
});
return { logged: true };
}
Event Differences Table¶
| Field | record_created | record_updated | record_deleted | record_restored | record_reverted |
|---|---|---|---|---|---|
data structure | Full record | { before, after } | Full record | { before, after } | { before, after } |
Initial version | 1 | Varies | Varies | Varies | Varies |
version changes | N/A | Incremented | N/A | Incremented | Incremented |
| Previous data available | No | Yes (in before) | No (is current) | Yes (in before) | Yes (in before) |
| User field | createdBy | updatedBy | deletedBy | restoredBy | revertedBy |
| Can detect changes | N/A | Yes | N/A | Yes | Yes |
Common Patterns¶
Pattern 1: Conditional Processing Based on Changed Fields¶
async function run() {
const { event, data } = executionParams;
// Only process updates where specific fields changed
if (event === "record_updated") {
const { before, after } = data;
// Only proceed if 'status' field changed
if (before.data.status === after.data.status) {
api.log({ message: "Status unchanged, skipping" });
return { skipped: true, reason: "no_status_change" };
}
}
// Process the event...
return { success: true };
}
Pattern 2: Combining Trigger Params with Event Data¶
async function run() {
const { recordId, data, event } = executionParams;
// Static config from trigger
const webhookUrl = triggerParams.webhookUrl;
const includeFullRecord = triggerParams.includeFullRecord;
const payload = {
event,
recordId,
timestamp: executionParams.timestamp
};
if (includeFullRecord) {
payload.record = event === "record_updated" ? data.after : data;
}
await api.http.post(webhookUrl, payload);
return { success: true };
}
Pattern 3: Handling Multiple Event Types in One Function¶
async function run() {
const { event, recordId, data } = executionParams;
switch (event) {
case "record_created":
await handleCreated(recordId, data);
break;
case "record_updated":
await handleUpdated(recordId, data.before, data.after);
break;
case "record_deleted":
await handleDeleted(recordId, data);
break;
default:
api.log({ message: "Unknown event type", event });
}
return { success: true, event };
}
async function handleCreated(recordId, record) {
api.log({ message: "New record", recordId });
// ... creation logic
}
async function handleUpdated(recordId, before, after) {
api.log({
message: "Record updated",
recordId,
versionBefore: before.version,
versionAfter: after.version
});
// ... update logic
}
async function handleDeleted(recordId, record) {
api.log({ message: "Record deleted", recordId });
// ... deletion logic
}
Related Documentation¶
- Function Triggers API - Creating and managing triggers
- Function Code Guide - Writing function code
- Compute Functions - Overview of compute functions