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.
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
| Type | Starts a run when… | Use it for |
|---|---|---|
webhook | An external system calls the trigger's webhook URL. | Event-driven pipelines — a push to a repository, an upstream job finishing, a third-party callback. |
schedule | A 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.