Skip to content

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

  1. You create a trigger linked to a function, specifying the event type and structure (via recordSlug)
  2. When a matching record event occurs, Centrali automatically executes your function
  3. 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:

https://api.centrali.io/data/workspace/YOUR_WORKSPACE/api/v1/http-trigger/payments/stripe

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

  1. Name triggers descriptively — Use names like notify-on-new-order or daily-sales-report, not trigger-1.

  2. Encrypt sensitive parameters — Always use { "value": "...", "encrypt": true } for API keys, secrets, and credentials.

  3. 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.

  4. Keep event-driven functions fast — They run on every matching event. Offload heavy processing to scheduled or on-demand triggers.

  5. 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.

  6. Set timezones explicitly — Cron and once triggers default to UTC. Always set timezone if your schedule is business-hours dependent.

  7. Monitor execution logs — Check function runs regularly via the API or Console to catch failures early. See Monitoring & Debugging.