Skip to content

Triggers

Triggers are inbound webhooks that let external services create tasks or instantiate pipelines in OpenGate. When an event occurs in a third-party system — a form submission, a CI/CD build, a monitoring alert — it can send an HTTP request to a trigger endpoint and kick off work automatically.

Each trigger has a unique endpoint:

POST /api/webhooks/trigger/:trigger_id

Replace :trigger_id with the ID of your trigger. For example:

POST https://app.opengate.example.com/api/webhooks/trigger/trg_abc123

The request body must be JSON:

Terminal window
curl -X POST https://app.opengate.example.com/api/webhooks/trigger/trg_abc123 \
-H "Content-Type: application/json" \
-H "X-OpenGate-Secret: $SIGNATURE" \
-d '{"title": "Deploy failed", "environment": "production", "commit": "a1b2c3d"}'

Trigger endpoints are authenticated using HMAC-SHA256 signatures. Each trigger has a secret key generated when it is created.

  1. Compute an HMAC-SHA256 digest of the raw request body using the trigger’s secret key.
  2. Send the hex-encoded digest in the X-OpenGate-Secret header.
import hmac
import hashlib
import requests
import json
secret = "whsec_your_trigger_secret"
payload = json.dumps({"title": "Deploy failed", "environment": "production"})
signature = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
requests.post(
"https://app.opengate.example.com/api/webhooks/trigger/trg_abc123",
headers={
"Content-Type": "application/json",
"X-OpenGate-Secret": signature,
},
data=payload,
)
const crypto = require("crypto");
const secret = "whsec_your_trigger_secret";
const payload = JSON.stringify({ title: "Deploy failed", environment: "production" });
const signature = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
fetch("https://app.opengate.example.com/api/webhooks/trigger/trg_abc123", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-OpenGate-Secret": signature,
},
body: payload,
});

OpenGate verifies the signature on every request. Requests with missing or invalid signatures are rejected with 401 Unauthorized.

Trigger actions can reference fields from the incoming webhook payload using double-brace syntax:

{{payload.field}}

This lets you dynamically populate task titles, descriptions, and other fields based on the data sent by the external service.

Given this incoming payload:

{
"title": "Deploy failed",
"environment": "production",
"commit": "a1b2c3d",
"author": "jane"
}

You can configure a trigger’s task title as:

[{{payload.environment}}] {{payload.title}}

Which resolves to:

[production] Deploy failed

And a description template like:

Commit {{payload.commit}} by {{payload.author}} triggered this task.

Resolves to:

Commit a1b2c3d by jane triggered this task.

You can access nested fields with dot notation:

{{payload.repository.name}}
{{payload.alert.severity}}

If a referenced field is missing from the payload, the placeholder is replaced with an empty string.

Each trigger is configured with an action that determines what happens when a webhook is received.

Creates a new task in a specified list.

FieldDescription
list_idThe target list for the new task.
titleTask title. Supports {{payload.*}} interpolation.
descriptionTask description. Supports {{payload.*}} interpolation.
assigneesOptional. Array of user IDs to assign.
priorityOptional. One of urgent, high, normal, low.
tagsOptional. Array of tag names.

Example trigger configuration:

{
"action": "create_task",
"config": {
"list_id": "lst_xyz789",
"title": "[{{payload.environment}}] {{payload.title}}",
"description": "Commit: {{payload.commit}}\nAuthor: {{payload.author}}",
"priority": "high",
"tags": ["automated", "deploy"]
}
}

Starts a new instance of a pipeline, optionally passing payload data as pipeline variables.

FieldDescription
pipeline_idThe pipeline to instantiate.
variablesOptional. Key-value map passed to the pipeline. Supports {{payload.*}} interpolation.

Example trigger configuration:

{
"action": "instantiate_pipeline",
"config": {
"pipeline_id": "pip_def456",
"variables": {
"environment": "{{payload.environment}}",
"commit_sha": "{{payload.commit}}",
"triggered_by": "{{payload.author}}"
}
}
}

For additional security, you can restrict which IP addresses are allowed to invoke a trigger. When an IP allowlist is configured, requests from addresses not on the list are rejected with 403 Forbidden — even if the HMAC signature is valid.

Set the allowlist in the trigger settings:

{
"ip_allowlist": [
"203.0.113.0/24",
"198.51.100.42"
]
}

Both individual IPs and CIDR ranges are supported.

ServiceIP Ranges
GitHub WebhooksSee GitHub’s meta API for current ranges
GitLabCheck your instance’s outbound IPs
SlackSee Slack’s IP ranges documentation

When no allowlist is configured, the trigger accepts requests from any IP (authentication via HMAC signature is still required).

If a trigger secret leaks, rotate it without deleting the trigger:

Terminal window
curl -X POST <base-url>/api/projects/<project-id>/triggers/<trigger-id>/rotate-secret \
-H "Authorization: Bearer <your-token>"

Response:

{
"secret": "new-raw-secret",
"old_secret_expires_at": "2026-03-03T09:00:00Z",
"grace_period_hours": 24
}

The new secret is returned once — store it immediately. The old secret remains valid for 24 hours (grace period) so you have time to update integrations. After the grace period, only the new secret works.

In the dashboard, click the (rotate) button on a trigger card, confirm the dialog, then copy the new secret from the reveal banner.