Triggers¶
Overview¶
Triggers define when and how your compute functions execute. A function contains the code; a trigger controls when that code runs.
Every function needs at least one trigger to execute. A single function can have multiple triggers — for example, the same order-processing function might run on new records (event-driven) and be invocable manually for retries (on-demand).
Trigger Types¶
Centrali supports four trigger types:
| Type | How It Fires | Best For |
|---|---|---|
| Event-driven | Automatically when records change | Workflows, notifications, data sync |
| Scheduled | On a time-based schedule | Reports, cleanup, periodic sync |
| On-demand | Manual API call or SDK invocation | Admin tools, testing, one-off tasks |
| HTTP | External HTTP request to a URL | Webhooks from third parties (Stripe, GitHub, etc.) |
Understanding Parameter Shapes
The #1 source of confusion with triggers is what data your function actually receives. The shape of executionParams is different for every trigger type — and for event-driven triggers, it varies by event. See the Trigger Parameters & Payload Shapes guide for complete examples of every shape.
Event-Driven Triggers¶
Event-driven triggers fire automatically when record events occur in your workspace. They are the most common trigger type.
Supported Events¶
| Event | When It Fires |
|---|---|
record_created | After a new record is created |
record_updated | After an existing record is updated |
record_deleted | After a record is deleted (soft or hard) |
record_restored | After a deleted record is restored |
record_reverted | After a record is reverted to a previous version |
There are also failure events (record_created_failed, record_updated_failed, record_deleted_failed) for error-handling workflows.
How It Works¶
- You create a trigger linked to a function, specifying the event type and structure (via
recordSlug) - When a matching record event occurs, Centrali automatically executes your function
- The event data (record ID, record data, before/after values for updates) is passed as
executionParams
Example: Send notification on new order¶
curl -X POST "$CENTRALI_URL/data/workspace/$WORKSPACE/api/v1/function-triggers" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "notify-on-new-order",
"description": "Send Slack notification when a new order is created",
"functionId": "YOUR_FUNCTION_ID",
"executionType": "event-driven",
"triggerMetadata": {
"event": "record_created",
"recordSlug": "orders",
"params": {
"slackWebhookUrl": "https://hooks.slack.com/services/..."
}
}
}'
Accessing Event Data¶
In your function, the event payload is available via executionParams:
async function run() {
const { event, recordId, recordSlug, data } = executionParams;
if (event === "record_created") {
// data is the full record
api.log({ message: `New ${recordSlug} created`, recordId });
}
if (event === "record_updated") {
// data contains { before, after }
const statusChanged = data.before.data.status !== data.after.data.status;
if (statusChanged) {
api.log({ message: "Status changed", from: data.before.data.status, to: data.after.data.status });
}
}
return { success: true };
}
For full payload documentation, see the Event Payloads Reference.
When to Use Event-Driven Triggers¶
- Sending notifications when data changes
- Keeping derived data in sync (e.g., recalculating totals when line items change)
- Cascading updates across structures
- Audit logging
- Integrating with external systems in real time
Scheduled Triggers¶
Scheduled triggers run your function automatically based on time. There are three schedule types.
Interval¶
Run a function repeatedly every N seconds.
curl -X POST "$CENTRALI_URL/data/workspace/$WORKSPACE/api/v1/function-triggers" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "sync-inventory",
"functionId": "YOUR_FUNCTION_ID",
"executionType": "scheduled",
"triggerMetadata": {
"scheduleType": "interval",
"interval": 300
}
}'
Common intervals: 60 (every minute), 300 (5 minutes), 3600 (hourly), 86400 (daily).
Cron¶
Run on a cron schedule. Uses the standard 5-field format: minute hour day month weekday.
curl -X POST "$CENTRALI_URL/data/workspace/$WORKSPACE/api/v1/function-triggers" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "daily-report",
"functionId": "YOUR_FUNCTION_ID",
"executionType": "scheduled",
"triggerMetadata": {
"scheduleType": "cron",
"cronExpression": "0 9 * * 1-5",
"timezone": "America/New_York"
}
}'
| Expression | Description |
|---|---|
0 9 * * * | Every day at 9:00 AM |
0 9 * * 1-5 | Weekdays at 9:00 AM |
*/15 * * * * | Every 15 minutes |
0 0 1 * * | First day of each month at midnight |
Once¶
Run a single time at a specific datetime. The scheduledAt value must be in the future.
curl -X POST "$CENTRALI_URL/data/workspace/$WORKSPACE/api/v1/function-triggers" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "launch-campaign",
"functionId": "YOUR_FUNCTION_ID",
"executionType": "scheduled",
"triggerMetadata": {
"scheduleType": "once",
"scheduledAt": "2026-03-01T09:00:00Z",
"timezone": "America/New_York"
}
}'
Pause and Resume¶
Scheduled triggers can be paused and resumed without deleting them:
# Pause
curl -X PATCH "$CENTRALI_URL/data/workspace/$WORKSPACE/api/v1/function-triggers/TRIGGER_ID/pause" \
-H "Authorization: Bearer $TOKEN"
# Resume
curl -X PATCH "$CENTRALI_URL/data/workspace/$WORKSPACE/api/v1/function-triggers/TRIGGER_ID/resume" \
-H "Authorization: Bearer $TOKEN"
When to Use Scheduled Triggers¶
- Generating periodic reports
- Data cleanup and archival
- Syncing data with external systems
- Cache warming or invalidation
- Health checks and monitoring
On-Demand Triggers¶
On-demand triggers execute only when you explicitly invoke them via the API or SDK.
Creating and Executing¶
# Create the trigger with static configuration
curl -X POST "$CENTRALI_URL/data/workspace/$WORKSPACE/api/v1/function-triggers" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "manual-export",
"functionId": "YOUR_FUNCTION_ID",
"executionType": "on-demand",
"triggerMetadata": {
"params": {
"format": "csv",
"batchSize": 1000
}
}
}'
# Execute it with runtime parameters
curl -X POST "$CENTRALI_URL/data/workspace/$WORKSPACE/api/v1/function-triggers/TRIGGER_ID/execute" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"recordType": "orders",
"startDate": "2026-01-01"
}'
Using the SDK¶
const result = await centrali.invokeFunction('manual-export', {
recordType: 'orders',
startDate: '2026-01-01'
});
Two Types of Parameters¶
On-demand triggers distinguish between static and runtime parameters:
triggerParams— Set when creating the trigger. Good for API keys, configuration, and defaults.executionParams— Passed at execution time. Good for per-invocation data like record IDs or filters.
async function run() {
// Static config from trigger setup
const format = triggerParams.format; // "csv"
const batchSize = triggerParams.batchSize; // 1000
// Runtime data from this specific execution
const recordType = executionParams.recordType; // "orders"
const startDate = executionParams.startDate; // "2026-01-01"
// ... process data
return { success: true };
}
When to Use On-Demand Triggers¶
- Admin tools and dashboards
- Data migrations
- Testing and debugging functions
- User-initiated actions (export, recalculate)
- Retry workflows
HTTP Triggers¶
HTTP triggers create a public URL that executes your function when called. This is ideal for receiving webhooks from third-party services.
Creating an HTTP Trigger¶
curl -X POST "$CENTRALI_URL/data/workspace/$WORKSPACE/api/v1/function-triggers" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "stripe-webhook",
"functionId": "YOUR_FUNCTION_ID",
"executionType": "http-trigger",
"triggerMetadata": {
"path": "/payments/stripe",
"params": {
"signingSecret": {
"value": "whsec_abc123",
"encrypt": true
}
}
}
}'
The trigger URL will be:
Accessing the HTTP Payload¶
The incoming request body is available as executionParams:
async function run() {
// The HTTP request body
const event = executionParams;
// Verify webhook signature using encrypted secret
const signature = event.headers?.['stripe-signature'];
const expectedSig = api.hmacSha256(triggerParams.signingSecret, JSON.stringify(event.body));
api.log({ message: 'Webhook received', type: event.body?.type });
return { success: true };
}
When to Use HTTP Triggers¶
- Payment gateway callbacks (Stripe, PayPal)
- CI/CD pipeline notifications (GitHub, GitLab)
- Form submissions from external sites
- Third-party service integrations
- IoT device events
Encrypted Parameters¶
Sensitive values like API keys and webhook secrets can be encrypted at rest. Add "encrypt": true to any parameter:
{
"triggerMetadata": {
"params": {
"publicSetting": "visible-in-api",
"apiKey": {
"value": "sk_live_abc123",
"encrypt": true
}
}
}
}
Encrypted parameters:
- Are stored using AES-256-GCM encryption
- Appear as encrypted objects in API responses (you cannot read the plaintext back)
- Are automatically decrypted before your function executes
- Are available as plain values in
triggerParams
Multiple Triggers Per Function¶
A single function can have multiple triggers. This is useful when the same logic needs to run in different contexts:
Function: "process-order"
├── Trigger 1: event-driven (record_created on "orders")
├── Trigger 2: on-demand (manual retry from admin panel)
└── Trigger 3: http-trigger (incoming webhook from partner API)
Each trigger can have different triggerMetadata.params, so the same function can behave differently depending on how it was invoked. Check executionParams to determine the source:
async function run() {
if (executionParams.event) {
// Triggered by a record event
api.log({ message: 'Event-driven execution' });
} else if (executionParams.headers) {
// Triggered by HTTP webhook
api.log({ message: 'HTTP trigger execution' });
} else {
// On-demand or scheduled
api.log({ message: 'Manual/scheduled execution' });
}
return { success: true };
}
Choosing the Right Trigger Type¶
| Scenario | Trigger Type |
|---|---|
| "When a new user signs up, send a welcome email" | Event-driven (record_created) |
| "Every night at midnight, generate a report" | Scheduled (cron) |
| "Every 5 minutes, sync data from external API" | Scheduled (interval) |
| "Admin clicks 'Export' button in dashboard" | On-demand |
| "Stripe sends a payment confirmation" | HTTP trigger |
| "Run a one-time data migration next Tuesday" | Scheduled (once) |
| "When an order is updated, recalculate totals" | Event-driven (record_updated) |
Best Practices¶
-
Name triggers descriptively — Use names like
notify-on-new-orderordaily-sales-report, nottrigger-1. -
Encrypt sensitive parameters — Always use
{ "value": "...", "encrypt": true }for API keys, secrets, and credentials. -
Use on-demand triggers for retry — Pair event-driven triggers with an on-demand trigger on the same function so you can manually retry failures.
-
Keep event-driven functions fast — They run on every matching event. Offload heavy processing to scheduled or on-demand triggers.
-
Use cron over interval for specific times — If you need "every day at 9 AM", use cron (
0 9 * * *). Interval-based triggers drift over time and don't respect timezones. -
Set timezones explicitly — Cron and once triggers default to UTC. Always set
timezoneif your schedule is business-hours dependent. -
Monitor execution logs — Check function runs regularly via the API or Console to catch failures early. See Monitoring & Debugging.
Related Documentation¶
- Trigger Parameters & Payload Shapes — Exact
executionParamsshape for every trigger type and event - Compute Functions — Creating and managing functions
- Writing Functions — Function code guide and API reference
- Function Triggers API — Complete API endpoints reference
- Event Payloads Reference — Full event payload structures
- Function Re-run — Re-running previous executions
- Orchestrations — Chaining multiple functions together