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, in the Webhook trigger card. 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
If the workflow is turned off, the call is rejected with
409and nothing is recorded in the execution history. → 10. Executions and Monitoring
Blocking forged requests with a signature¶
Anyone who knows the webhook URL can trigger the workflow. To stop that, register a workspace secret
named WEBHOOK_SECRET.
From the moment it exists, every webhook in that workspace requires a signature. The signature is
the HMAC-SHA256 hex digest of the whole request body, keyed with WEBHOOK_SECRET, sent in either
of these headers.
| Header | Format | Used by |
|---|---|---|
X-Webhook-Signature |
the hex string as-is | systems you build yourself |
X-Hub-Signature-256 |
sha256= + hex |
GitHub webhooks, exactly as they send it |
If both arrive, X-Webhook-Signature wins. A missing or wrong signature means the workflow does not run.
BODY='{"orderId":"ORD-1234"}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -hex | awk '{print $2}')
curl -X POST "https://api.eeumsae.com/webhooks/<workspaceId>/order-notify" \
-H "Content-Type: application/json" \
-H "X-Webhook-Signature: $SIG" \
-d "$BODY"
To wire up a GitHub webhook, just put the same value in the repository's Settings → Webhooks → Secret.
GitHub attaches X-Hub-Signature-256 on its own and eeumsae verifies it as-is.
WEBHOOK_SECREThas to be registered as a secret (sensitive). Registering it as a plain variable does not turn verification on. → 08. Variables and Secrets
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.
Pausing a schedule¶
Turn the workflow off instead of deleting it and the cron stops firing. Use this when something needs fixing but the daily alert keeps going out. → 10. Executions and Monitoring
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