Webhook Trigger
Create a Webhook, bind API Key authentication (HMAC for legacy integrations), and map payload variables so external systems can drive your workflows.
A Webhook lets external systems (GitHub, CI/CD, Lark, IoT, an upstream API) start a workflow execution directly via HTTP POST. Recommended approach: bind the Webhook to an API Key with the WEBHOOK_TRIGGER scope and authenticate trigger requests with that Key.
Create a Webhook and Bind an API Key
- Under Console → Account settings → API keys, create a Key and check the scope
WEBHOOK_TRIGGER(seeAPI Keys and scopes) - Create a Webhook from the Webhook list or the workflow details page, choose the target workflow, and bind this Key. The creator needs edit permission on the workflow, and the bound Key must be their own
You can also use the management API (with a logged-in console session):
curl -X POST https://braidrun.com/api/webhooks \
-H "Authorization: Bearer <console-token>" \
-H "Content-Type: application/json" \
-d '{
"workflowId": "<workflow-id>",
"name": "GitHub Push Webhook",
"apiKeyId": "<api-key-id>",
"variableMapping": {
"branch": "ref",
"repo_name": "repo"
}
}'The response includes a unique webhook-id. The trigger URL is:
POST https://braidrun.com/api/webhooks/<webhook-id>/triggerWebhook count scales with your plan: 3 on Pro, 10 on Team.
Trigger Workflow
curl -X POST https://braidrun.com/api/webhooks/<webhook-id>/trigger \
-H "Authorization: Bearer dyk_<id>_<secret>" \
-H "Content-Type: application/json" \
-d '{
"ref": "refs/heads/main",
"repo": "my-app"
}'Credentials can be passed in three ways, which the server checks in this order:
Authorization: Bearer dyk_<id>_<secret> # 推荐
X-API-Key: dyk_<id>_<secret> # 无法自定义 Authorization 头时
POST .../trigger?api_key=dyk_<id>_<secret> # 仅限无法设置 header 的场景Successful trigger returns:
{
"executionId": "exec_a3b9c8...",
"webhookId": "<webhook-id>",
"workflowId": "<workflow-id>",
"status": "PENDING",
"startedAt": 1735632891234
}The request body must be a JSON object, up to 1 MB. An empty body is treated as an empty object; invalid JSON returns 400.
Variable mapping
Without variableMapping, top-level string, number, and boolean fields in the payload map to workflow variables of the same name automatically; nested objects and arrays are excluded from automatic mapping.
To rename, configure variableMapping : the key is the workflow variable name, the value is the top-level payload field name. Only top-level fields are supported; nested path lookups are not.
# Webhook 配置
"variableMapping": { "branch": "ref", "repo_name": "repo" }
# 触发 payload
{ "ref": "refs/heads/main", "repo": "my-app" }
# 工作流实际拿到的输入
{ "branch": "refs/heads/main", "repo_name": "my-app" }If a mapped field is missing from the payload, the variable is not injected and the default value in the workflow template still applies (it won't be overwritten with an empty string).
HMAC Signatures (for Legacy Integrations)
A Webhook with no API Key bound but with secretKey set uses the legacy HMAC mode: the trigger request must include a signature in the header:
X-Webhook-Signature: sha256=<hex(HMAC-SHA256(rawRequestBody, secretKey))>Signature = HmacSHA256(rawRequestBody, secretKey) , output as a hex string, with or without the sha256= prefix. A mismatch returns 401.
The signature is the original byte stream. Do not do formatting/key sorting before calculation, otherwise the signature will not match.
A Webhook with an API Key bound no longer accepts HMAC signatures (even if the secretKey field still has a value); migrating to API Key is one-way. A Webhook with neither auth method configured doesn't verify identity on trigger—the URL itself acts as the credential, which we recommend only during debugging.
The legacy trigger path POST /api/webhook-trigger/{webhookId} is still available with identical behavior; use the canonical path above for new integrations.
Error Responses
| Status Code | Meaning |
|---|---|
400 | The request body is not valid JSON |
401 | The API Key is invalid, lacks the WEBHOOK_TRIGGER scope, isn't the key bound to this Webhook, or the HMAC signature doesn't match |
404 | The webhook-id doesn't exist |
409 | The Webhook is disabled |
429 | Triggered too frequently; the response includes Retry-After and X-RateLimit-* headers |
Common Access Scenarios
- GitHub push — Map the branch name and commit author to variables; the workflow builds, tests, and deploys automatically
- CI 系统 — Build completed → Webhook triggers subsequent release pipeline
- Lark / 飞书机器人 — Trigger operational batch processing after receiving a specific command
- IoT 上报 — Device alarm → Webhook triggers troubleshooting workflow and converges alarms
Management Endpoints
List GET /api/webhooks, update PUT /api/webhooks/{id}, delete DELETE /api/webhooks/{id}, plus GET /api/webhooks/{id}/stats returns trigger stats; all of these are authenticated console endpoints.
When Service Restarts
A Webhook-triggered execution interrupted by a service restart won't auto-resume: the payload is handled at-most-once, and the platform doesn't replay it. Executions already paused at manual_approval are the exception—they continue as usual once approved. To rerun, have the upstream system send the trigger request again (this creates a new execution).