Triggers
Triggers are the entry points that start your Cronflow workflows. They define when and how workflows are executed, supporting multiple trigger types for different use cases.
Trigger Types
Cronflow supports several trigger types:
- Webhook Triggers - HTTP endpoints for external integrations
- Schedule Triggers - Time-based execution using cron expressions
- Event Triggers - Custom events for decoupled workflows
- Manual Triggers - Manual execution via API calls
Webhook Triggers
Webhook triggers create HTTP endpoints that can receive external requests and start workflows.
Basic Webhook
import { cronflow } from "cronflow";
const workflow = cronflow.define({
id: "order-processor",
name: "Order Processing Workflow",
});
workflow
.onWebhook("/webhooks/orders", {
method: "POST",
schema: z.object({
orderId: z.string().uuid(),
customerId: z.string(),
amount: z.number().positive(),
}),
})
.step("process-order", async (ctx) => {
return await processOrder(ctx.payload);
});
Webhook with Headers Validation
workflow.onWebhook("/webhooks/stripe", {
method: "POST",
headers: {
required: {
"stripe-signature": "whsec_...",
"content-type": "application/json",
},
validate: (headers) => {
// Custom header validation
if (!headers["user-agent"]?.includes("Stripe")) {
return "Invalid user agent";
}
return true;
},
},
schema: z.object({
id: z.string(),
type: z.string(),
data: z.object({
object: z.object({
id: z.string(),
amount: z.number(),
}),
}),
}),
});
Webhook with Framework Integration
import express from "express";
const app = express();
const workflow = cronflow.define({
id: "api-workflow",
});
workflow.onWebhook("/api/orders", {
app: "express",
appInstance: app,
method: "POST",
schema: z.object({
orderId: z.string(),
items: z.array(
z.object({
id: z.string(),
quantity: z.number(),
})
),
}),
});
Custom Framework Integration
When your framework is not natively supported, you can use the registerRoute
option to integrate with any framework:
// Custom framework integration
workflow.onWebhook("/custom/webhook", {
registerRoute: (method, path, handler) => {
myFramework[method.toLowerCase()](path, handler);
},
});
Webhook Response Handling
workflow.onWebhook("/webhooks/orders", {
method: "POST",
trigger: "process-order", // Trigger specific step
onSuccess: (ctx) => {
console.log("✅ Webhook processed successfully");
},
onError: (ctx, error) => {
console.error("❌ Webhook processing failed:", error);
},
});
Schedule Triggers
Schedule triggers execute workflows at specified times using cron expressions.
Basic Schedule
workflow.onSchedule("0 2 * * *"); // Run at 2 AM daily
Common Schedule Patterns
// Every minute
workflow.onSchedule("* * * * *");
// Every hour
workflow.onSchedule("0 * * * *");
// Every day at midnight
workflow.onSchedule("0 0 * * *");
// Every Monday at 9 AM
workflow.onSchedule("0 9 * * 1");
// Every 15 minutes
workflow.onSchedule("*/15 * * * *");
// First day of every month
workflow.onSchedule("0 0 1 * *");
Interval-based Scheduling
// Every 5 minutes
workflow.onInterval("5m");
// Every 2 hours
workflow.onInterval("2h");
// Every day
workflow.onInterval("1d");
Event Triggers
Event triggers allow workflows to respond to custom events published by your application.
Basic Event Trigger
workflow.onEvent("user.registered");
Publishing Events
import { cronflow } from "cronflow";
// Publish an event
await cronflow.publishEvent("user.registered", {
userId: "123",
email: "user@example.com",
timestamp: new Date(),
});
// Publish with additional data
await cronflow.publishEvent("order.completed", {
orderId: "456",
amount: 99.99,
customerId: "789",
});
Event with Payload Validation
workflow.onEvent("order.created", {
schema: z.object({
orderId: z.string(),
customerId: z.string(),
amount: z.number().positive(),
}),
});
Manual Triggers
Manual triggers allow workflows to be started programmatically.
Basic Manual Trigger
workflow.manual();
Triggering Manually
// Trigger the workflow
const runId = await cronflow.trigger("order-processor", {
orderId: "123",
customerId: "456",
items: [
{ id: "item1", quantity: 2 },
{ id: "item2", quantity: 1 },
],
});
console.log("Workflow started with run ID:", runId);
Advanced Trigger Configurations
Multiple Triggers
Workflows can have multiple triggers:
workflow
.onWebhook("/webhooks/orders")
.onSchedule("0 2 * * *") // Also run daily at 2 AM
.onEvent("order.urgent")
.manual();
Trigger with Middleware
workflow.onWebhook("/webhooks/orders", {
method: "POST",
middleware: [
async (req, res, next) => {
// Rate limiting
const clientId = req.headers["x-client-id"];
if (!clientId) {
return res.status(401).json({ error: "Missing client ID" });
}
next();
},
async (req, res, next) => {
// Authentication
const token = req.headers.authorization;
if (!token || !isValidToken(token)) {
return res.status(401).json({ error: "Invalid token" });
}
next();
},
],
});
Conditional Triggers
workflow.onWebhook("/webhooks/orders", {
method: "POST",
condition: (req) => {
// Only trigger for orders above $100
return req.body.amount > 100;
},
});
Trigger Validation
Schema Validation
import { z } from "zod";
const orderSchema = z.object({
orderId: z.string().uuid(),
customerId: z.string(),
items: z.array(
z.object({
id: z.string(),
quantity: z.number().positive(),
price: z.number().positive(),
})
),
shippingAddress: z.object({
street: z.string(),
city: z.string(),
zipCode: z.string(),
}),
});
workflow.onWebhook("/webhooks/orders", {
schema: orderSchema,
});
Custom Validation
workflow.onWebhook("/webhooks/orders", {
validate: (payload) => {
if (payload.amount > 10000) {
return "Orders above $10,000 require manual review";
}
return true;
},
});
Trigger Error Handling
Webhook Error Responses
workflow.onWebhook("/webhooks/orders", {
onError: (ctx, error) => {
console.error("Webhook processing failed:", error);
// Return custom error response
return {
status: 400,
body: {
error: "Invalid order data",
details: error.message,
},
};
},
});
Retry Configuration
workflow.onWebhook("/webhooks/orders", {
retry: {
attempts: 3,
backoff: { delay: "5s" },
},
});
Trigger Monitoring
Trigger Statistics
// Get trigger statistics
const stats = await cronflow.getTriggerStats();
console.log("Trigger stats:", stats);
// Get workflow triggers
const triggers = await cronflow.getWorkflowTriggers("order-processor");
console.log("Workflow triggers:", triggers);
Schedule Triggers
// Get all schedule triggers
const schedules = await cronflow.getScheduleTriggers();
console.log("Schedule triggers:", schedules);
Best Practices
1. Use Descriptive Trigger Paths
// ✅ Good: Descriptive paths
workflow.onWebhook("/webhooks/stripe/payment-succeeded");
workflow.onWebhook("/webhooks/shopify/order-created");
// ❌ Avoid: Generic paths
workflow.onWebhook("/webhook");
workflow.onWebhook("/api");
2. Validate Input Data
workflow.onWebhook("/webhooks/orders", {
schema: z.object({
orderId: z.string().uuid(),
amount: z.number().positive(),
customerEmail: z.string().email(),
}),
});
3. Handle Errors Gracefully
workflow.onWebhook("/webhooks/orders", {
onError: (ctx, error) => {
console.error("Webhook error:", error);
// Don't throw - return error response
return {
status: 400,
body: { error: "Invalid request" },
};
},
});
4. Use Appropriate HTTP Methods
// For creating resources
workflow.onWebhook("/webhooks/orders", { method: "POST" });
// For updates
workflow.onWebhook("/webhooks/orders/:id", { method: "PUT" });
// For deletions
workflow.onWebhook("/webhooks/orders/:id", { method: "DELETE" });
5. Implement Rate Limiting
workflow.onWebhook("/webhooks/orders", {
middleware: [
rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
}),
],
});
API Reference
workflow.onWebhook(path, options?)
Creates a webhook trigger.
Parameters:
path
(string): Webhook endpoint pathoptions
(WebhookOptions, optional): Webhook configuration
workflow.onSchedule(cronExpression, options?)
Creates a schedule trigger.
Parameters:
cronExpression
(string): Cron expressionoptions
(ScheduleOptions, optional): Schedule configuration
workflow.onEvent(eventName, options?)
Creates an event trigger.
Parameters:
eventName
(string): Event nameoptions
(EventOptions, optional): Event configuration
workflow.manual()
Creates a manual trigger.
Triggers are the foundation of workflow automation in Cronflow. Choose the right trigger type for your use case and configure them properly to build robust, reliable workflows.