See also: Triggers concept and configuration for what this API powers, when to call it, and how it is configured.
GET /api/v1/triggers
List all trigger rules sorted by priority descending.Query Parameters
Response
POST /api/v1/triggers
Create a new trigger rule.Request Body
Condition shape. A leaf rule is
{ "field": "<payloadKey>", "operator": "<op>", "value": <any> }; rules combine into groups with all (AND) or any (OR) — e.g. { "all": [ { "field": "amount", "operator": "gt", "value": 500 }, { "any": [ ... ] } ] }. Operators: eq, neq, gt, gte, lt, lte, in (value must be an array), exists. An unknown operator fails closed (the rule does not match). An empty or omitted condition always fires.Example
201 Created
GET /api/v1/triggers/
Get trigger rule details.PUT /api/v1/triggers/
Update a trigger rule. Only provided fields are updated.
Response:
200 OK
DELETE /api/v1/triggers/
Delete a trigger rule. Requires admin role. Response:204 No Content
POST /api/v1/triggers//test
Dry-run a trigger against a sample event payload. Returns whether the trigger would fire without actually executing the action.Request Body
Response
POST /api/v1/triggers/file-arrival
Push-based webhook that fires a data pipeline when a file lands. Unlike the trigger-rule endpoints above, this is a system webhook: it is not RBAC-gated — it self-authorizes with the sharedCRON_SECRET. Rate limited to 60 requests / minute per source IP. Returns 503 if
CRON_SECRET is not configured.
Authentication
One of:Authorization: Bearer <CRON_SECRET>headerX-Cron-Secret: <CRON_SECRET>headersecretfield in the request body (per-pipeline override; takes precedence)- A same-origin request carrying a valid session cookie (the editor’s “Fire now” button)
Request body
Two shapes are accepted:(bucket, key) pair against every active
irVersion: "1.0" pipeline that has a file_arrival trigger, and probes the source’s pattern to
confirm the key really matches before dispatching.
Behavior
The route confirms the resolved pipeline actually has afile_arrival trigger and belongs to the
asserted tenant, writes a PipelineRun row (triggerSource: "file_arrival"), then dispatches the
run in-process (fire-and-forget). Poll GET /api/v1/pipelines/{id}/runs for
the outcome.
Push and poll can’t double-load the same file. A pipeline may have both this
webhook and the in-process scheduler polling the
same inbox. Both paths claim the run under a transaction-scoped advisory lock keyed
on
(tenant, pipeline, objectKey) and stamp metadata.objectKey on the run row; a
claim first checks for an in-flight run with the same objectKey. So for a given
object, whichever path fires first wins and the other is a no-op — the file is loaded
exactly once regardless of how many triggers observe it.Response 202
Errors
POST /api/v1/triggers/eventbridge
Direct receiver for AWS EventBridge API Destinations that proxies to a/api/v1/cron/* endpoint —
an alternative to the Terraform Lambda hop for operators who prefer fewer moving parts. Not
RBAC-gated; authenticated with CRON_SECRET / CRON_TOKEN.
Authentication
- HMAC —
X-EventBridge-Signature: <hex>=HMAC-SHA256(CRON_SECRET, rawBody)(preferred), or - Shared secret —
X-Cron-Token,X-Cron-Secret, orAuthorization: Bearerequal to the secret.
401 (no body detail) when the secret is unset or verification fails.
Request body
cron_endpoint_path must be in the route’s allowlist (the /api/v1/cron/* jobs plus the legacy
/api/cron/tick); anything else returns 400. On a match the route self-calls that cron endpoint
(GET, forwarding the secret) and returns its result.
Response
400 = path not in allowlist, 502 = the
downstream self-call failed.
Roles
The trigger-rule endpoints are RBAC-gated:
The
file-arrival and eventbridge webhooks are not RBAC-gated — they self-authorize with
CRON_SECRET as described above.
See also: Triggers