03. Setting Up Triggers¶
This page is about deciding what wakes a workflow up. There are two ways.
| Kind | When it runs | Example |
|---|---|---|
Webhook (WEBHOOK) |
Every time someone calls the address | When an order arrives, when a form is submitted |
Schedule (SCHEDULER) |
At the times you set | Every morning at 9, every Monday |
Both are written on the ENTRYPOINT node. There is exactly one ENTRYPOINT per workflow.
Webhook triggers¶
The simplest form¶
If you leave trigger out entirely, webhook is the default. In that case the request body you receive is passed on to the next node whole and unchanged.
If you want the incoming data validated¶
Attach an input-schema and eeumsae will validate the request for you.
- id: trigger
name: Order webhook
type: ENTRYPOINT
trigger:
kind: WEBHOOK
input-schema:
type: object
required: [orderId, customerName]
properties:
orderId: { type: string }
customerName: { type: string }
amount: { type: number }
Using input-schema changes the behavior like this.
| Situation | Result |
|---|---|
A required field is missing from the request |
The execution fails |
The request contains a field not in properties |
It is dropped silently (it does not reach the next node) |
A field that is in properties |
Passed through normally |
In other words,
input-schemais a whitelist. Every field you plan to use later has to be listed inproperties. If you wrote a field and its value never arrives, check first whether you left it out ofproperties.
The call address¶
You can see and copy it on the workflow's Overview tab. The format is:
{workflowSlug} is the slug you chose when you created the workflow.
curl -X POST "https://api.eeumsae.com/webhooks/<workspaceId>/order-notify" \
-H "Content-Type: application/json" \
-d '{"orderId": "ORD-1234", "customerName": "Ada Lovelace", "amount": 25000}'
The call returns a response immediately, and the workflow runs asynchronously in the background. A 200 response does not mean the workflow succeeded — it means "received, thanks". Check the result in the execution history. → 10. Executions and Monitoring
Reading the received values¶
trigger here is the id of the ENTRYPOINT node. If you named the node my-trigger, it becomes ${nodes.my-trigger.response.body.orderId}.
Schedule triggers¶
Runs automatically at the times you set.
- id: trigger
name: Every morning trigger
type: ENTRYPOINT
trigger:
kind: SCHEDULER
cron: "0 0 9 * * ?"
timezone: "Asia/Seoul"
lookback: PT24H
| Field | Required | Description |
|---|---|---|
cron |
Required | A six-field cron expression (see below) |
timezone |
Optional | Defaults to UTC. If you mean local time, you must write it out — for example Asia/Seoul |
lookback |
Optional | Computes a query window for you and passes it along (see below) |
cron expressions have six fields¶
This differs from the five-field cron you usually see. A seconds field is prepended.
┌───────────── second (0-59)
│ ┌─────────── minute (0-59)
│ │ ┌───────── hour (0-23)
│ │ │ ┌─────── day of month (1-31)
│ │ │ │ ┌───── month (1-12)
│ │ │ │ │ ┌─── day of week (0-7, 0 and 7 are Sunday)
│ │ │ │ │ │
0 0 9 * * ?
Here are the common ones.
| What you want | cron |
|---|---|
| Every day at 9:00 | 0 0 9 * * ? |
| Every day at 9:30 | 0 30 9 * * ? |
| Every hour on the hour | 0 0 * * * ? |
| Every 30 minutes | 0 0/30 * * * ? |
| Weekdays (Mon-Fri) at 8:00 | 0 0 8 ? * MON-FRI |
| Every Monday at 10:00 | 0 0 10 ? * MON |
| Midnight on the 1st of every month | 0 0 0 1 * ? |
*and?: the day-of-month field and the day-of-week field conflict with each other, so one of them takes a?. If you are specifying by date, put?in the day-of-week field; if by weekday, put?in the day-of-month field.Watch the time zone: if you omit
timezoneyou get UTC. Writing only0 0 9 * * ?runs at 6 PM Korea time. To run on Korea time, be sure to includetimezone: "Asia/Seoul".
lookback — "just fetch the last 24 hours"¶
When you build a daily report, you always end up querying "the last day's worth". This feature has eeumsae compute the start and end of that window and pass them to you.
With this, two values appear in the trigger output.
| Value | Meaning |
|---|---|
${nodes.trigger.response.body.windowStart} |
Execution time − lookback |
${nodes.trigger.response.body.windowEnd} |
Execution time |
Both are ISO-8601 strings (for example 2026-05-19T09:00:00.000+09:00).
- id: fetch-orders
name: Fetch orders
type: CALL
integration: http_request
input:
uri: "https://api.example.com/orders"
method: GET
queryParams:
from: "${nodes.trigger.response.body.windowStart}"
to: "${nodes.trigger.response.body.windowEnd}"
The lookback value is written in ISO-8601 duration format.
| Window you want | Notation |
|---|---|
| 1 hour | PT1H |
| 6 hours | PT6H |
| 24 hours | PT24H |
| 7 days | P7D |
| 30 minutes | PT30M |
If you omit lookback, windowStart / windowEnd are never created at all. Referencing them raises an error during execution.
Comparing the two¶
| Webhook | Schedule | |
|---|---|---|
| Start condition | When called from outside | At the times you set |
| Input data | The request body (whatever you want) | None (window values if you use lookback) |
| Testing | Straight from curl |
Wait for the time, or run it immediately over MCP |
| Good for | Reacting to events (orders, sign-ups, inquiries) | Recurring reports, checks and syncs |
Next → 04. Integration Catalog