Skip to main content

Triggers

A trigger binds a workflow to a stage and starts runs automatically — either when an external system calls a webhook, or on a recurring schedule. Instead of every run being submitted by hand, a trigger lets the platform launch it for you while still using the version and configuration already bound to the stage.

Each trigger has a triggerId that is unique within its workflow and is used in the trigger's path. A workflow can own any number of triggers across its stages.

Triggers use stage config only

A trigger always runs the stage-bound version and configuration. Unlike an ad-hoc run, a trigger can never pass inline configuration — the target stage assignment is the single source of truth for what runs and with which parameters.

Two Trigger Types

TypeStarts a run when…Use it for
webhookAn external system calls the trigger's webhook URL.Event-driven pipelines — a push to a repository, an upstream job finishing, a third-party callback.
scheduleA cron schedule fires.Recurring pipelines — nightly retraining, hourly ingestion, periodic reports.

Creating a Trigger

Triggers are created with an idempotent upsert. The type and stage identify what the trigger does; the config object carries type-specific settings:

// PUT .../workflows/ml-training-pipeline/triggers/nightly-retrain
{
"type": "schedule",
"stage": "prod",
"enabled": true,
"config": {
"schedule": "0 2 * * *",
"timezone": "Europe/Berlin"
}
}

The API responds 201 when the trigger is created and 200 when an existing trigger is updated. Repeating the PUT never rotates a webhook secret — use :rotate-secret for that.

Webhook Triggers

A webhook trigger returns a one-time webhookUrl in its create response. This is the only time the secret is ever shown — only its hash is stored, and the plaintext is never recoverable, so capture it now:

// PUT .../workflows/ml-training-pipeline/triggers/on-push → 201
{
"workflowId": "ml-training-pipeline",
"triggerId": "on-push",
"type": "webhook",
"stage": "prod",
"enabled": true,
"config": { "signatureValidation": false },
"webhookUrl": "https://workflows.api.caip.bmw.cloud/v1/webhooks/8f3c…",
"createdAt": "2025-06-18T14:00:00.000Z",
"updatedAt": "2025-06-18T14:00:00.000Z"
}

Note that webhookUrl appears only in create and rotate responses — a GET or list of the trigger never returns it.

Invoking a Webhook

Fire the trigger by calling its URL. This starts a run for the trigger's stage assignment:

POST /v1/webhooks/8f3c…

The webhook endpoint lives under /v1 (not under /v1/spaces) — the secret in the path is what identifies the trigger.

Signature Validation

Set signatureValidation: true when you want to verify that a webhook call really came from a trusted caller. When enabled, the same secret embedded in the URL is also the HMAC-SHA256 signing key. The caller computes an HMAC over the raw request body and sends it in a header:

X-Signature-256: sha256=<hmac_hex>

Calls with a missing or invalid signature are rejected with 401.

Secret Rotation

To retire a leaked or aging secret, rotate it. This mints a fresh secret, invalidates the old URL, and returns a new one-time webhookUrl:

POST .../workflows/ml-training-pipeline/triggers/on-push:rotate-secret

Rotation applies to webhook triggers only.

Schedule Triggers

A schedule trigger runs on a 5-field cron schedule, evaluated in the trigger's timezone (an IANA name such as Europe/Berlin, defaulting to UTC):

// PUT .../workflows/ml-training-pipeline/triggers/nightly-retrain
{
"type": "schedule",
"stage": "prod",
"config": {
"schedule": "0 2 * * *",
"timezone": "Europe/Berlin"
}
}

Because a schedule trigger has no request body to draw from, the target stage must already have a stage assignment with both a version and a configuration. If either is missing the trigger is not created and the API responds 404. On success the platform schedules an Argo CronWorkflow that submits a run each time the schedule fires.

Enabling and Disabling

Every trigger has an enabled flag (default true). Setting enabled: false on a schedule trigger suspends its CronWorkflow without deleting the trigger — flip it back to true to resume. This is the clean way to pause a recurring pipeline during a freeze.

Manual Invocation for Testing

Any trigger can be invoked by hand — regardless of its type or whether it is enabled — to check that the wiring is correct:

POST .../workflows/ml-training-pipeline/triggers/nightly-retrain:invoke

This starts a run from the trigger's stage version and configuration, tagged with the trigger id — the exact path a schedule or webhook takes. If the target stage has no version assigned, the call is rejected with 422.

Deleting a Trigger

Deleting a trigger responds 204. For a schedule trigger, deletion also removes its Argo CronWorkflow so no further runs are scheduled.

Reference

See the full endpoint contract in the CAIP Workflows API Reference.