Flow Triggers¶
Complete reference for all flow trigger types and their event payloads.
Overview¶
Flows can be triggered by:
- Webhooks - HTTP POST from any service
- GitHub Events - PR, issue, push, release events
- GitLab Events - MR, issue, pipeline events
- Jira Events - Issue and comment events
- Schedules - Cron-based timing (coming soon)
This guide provides complete event payload structures for each trigger type.
Webhook Triggers¶
Configuration¶
Setup:
- Create flow with Trigger Type: Webhook
- Save the flow
- Copy the generated webhook URL
- Use the URL to trigger the flow from external services
Webhook URL Format:
Request Requirements:
- Method:
POST - Content-Type:
application/json - Body: Any valid JSON
Payload Structure¶
You control the payload structure completely. Send any JSON you need:
{
"event": "payment_received",
"timestamp": "2025-01-25T10:30:00Z",
"data": {
"amount": 1500,
"currency": "USD",
"customer_id": "cust_123",
"contract_id": "contract_456"
},
"metadata": {
"source": "payment_gateway",
"ip_address": "192.168.1.1"
}
}
Accessing in Prompt Template¶
All webhook payload data is available under trigger_event.payload:
Event Type: {{trigger_event.payload.event}}
Amount: ${{trigger_event.payload.data.amount}}
Customer: {{trigger_event.payload.data.customer_id}}
Contract: {{trigger_event.payload.data.contract_id}}
Source: {{trigger_event.payload.metadata.source}}
Example: Stripe Webhook¶
{
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_123",
"amount": 150000,
"currency": "usd",
"customer": "cus_123",
"metadata": {
"contract_id": "CONTRACT-2025-001"
}
}
}
}
Access in prompt:
Payment ID: {{trigger_event.payload.data.object.id}}
Amount: ${{trigger_event.payload.data.object.amount}}
Contract: {{trigger_event.payload.data.object.metadata.contract_id}}
Example: Custom Service Webhook¶
{
"alert_type": "server_down",
"severity": "critical",
"server": {
"hostname": "web-prod-01",
"ip": "10.0.1.50",
"region": "us-east-1"
},
"details": {
"error": "Connection timeout",
"last_seen": "2025-01-25T10:25:00Z"
}
}
Access in prompt:
Alert: {{trigger_event.payload.alert_type}}
Severity: {{trigger_event.payload.severity}}
Server: {{trigger_event.payload.server.hostname}}
Error: {{trigger_event.payload.details.error}}
GitHub Events¶
Common Fields¶
All GitHub events include these base fields:
{
"action": "opened|closed|reopened|edited|labeled|etc",
"repository": {
"id": 123456,
"name": "my-repo",
"full_name": "acme/my-repo",
"owner": {
"login": "acme",
"type": "Organization"
},
"html_url": "https://github.com/acme/my-repo",
"default_branch": "main"
},
"organization": {
"login": "acme",
"id": 789
},
"sender": {
"login": "username",
"id": 12345,
"type": "User"
}
}
Issue Events¶
issue_opened¶
Triggered when a new issue is created.
Event Type: issue_opened
Payload:
{
"action": "opened",
"issue": {
"id": 123456789,
"number": 42,
"title": "Bug: Application crashes on startup",
"body": "## Description\n\nThe application crashes immediately after launching...",
"state": "open",
"user": {
"login": "reporter_username",
"id": 12345
},
"assignee": null,
"assignees": [],
"labels": [
{
"name": "bug",
"color": "d73a4a"
}
],
"milestone": null,
"created_at": "2025-01-25T10:30:00Z",
"updated_at": "2025-01-25T10:30:00Z",
"html_url": "https://github.com/acme/my-repo/issues/42"
},
"repository": { ... },
"sender": { ... }
}
Access in prompt:
Issue #{{trigger_event.payload.issue.number}}: {{trigger_event.payload.issue.title}}
Body: {{trigger_event.payload.issue.body}}
Author: {{trigger_event.payload.issue.user.login}}
URL: {{trigger_event.payload.issue.html_url}}
Labels: {{trigger_event.payload.issue.labels}}
issue_updated¶
Triggered when issue is edited (title, body, labels changed, etc.).
Action values: edited, labeled, unlabeled, assigned, unassigned, milestoned, demilestoned
Payload: Same structure as issue_opened, but action field indicates what changed.
Additional fields when edited:
issue_closed¶
Triggered when issue is closed.
Payload: Same as issue_opened with action: "closed" and issue.state: "closed".
issue_reopened¶
Triggered when closed issue is reopened.
Payload: Same structure with action: "reopened".
Pull Request Events¶
pull_request_opened¶
Triggered when new PR is created.
Event Type: pull_request_opened
Payload:
{
"action": "opened",
"number": 123,
"pull_request": {
"id": 987654321,
"number": 123,
"title": "Add new feature",
"body": "## Changes\n\n- Added feature X\n- Fixed bug Y",
"state": "open",
"draft": false,
"merged": false,
"mergeable": true,
"mergeable_state": "clean",
"user": {
"login": "developer_username",
"id": 23456
},
"assignee": null,
"assignees": [],
"requested_reviewers": [
{
"login": "reviewer_username",
"id": 34567
}
],
"labels": [],
"milestone": null,
"head": {
"ref": "feature/new-feature",
"sha": "abc123def456",
"repo": {
"name": "my-repo",
"full_name": "acme/my-repo"
}
},
"base": {
"ref": "main",
"sha": "def456abc123",
"repo": {
"name": "my-repo",
"full_name": "acme/my-repo"
}
},
"created_at": "2025-01-25T11:00:00Z",
"updated_at": "2025-01-25T11:00:00Z",
"html_url": "https://github.com/acme/my-repo/pull/123"
},
"repository": { ... },
"sender": { ... }
}
Access in prompt:
PR #{{trigger_event.payload.pull_request.number}}: {{trigger_event.payload.pull_request.title}}
Author: {{trigger_event.payload.pull_request.user.login}}
Branch: {{trigger_event.payload.pull_request.head.ref}} → {{trigger_event.payload.pull_request.base.ref}}
URL: {{trigger_event.payload.pull_request.html_url}}
Draft: {{trigger_event.payload.pull_request.draft}}
Reviewers: {{trigger_event.payload.pull_request.requested_reviewers}}
pull_request_updated¶
Triggered when PR is edited or new commits are pushed.
Action values: edited, synchronize (new commits), labeled, unlabeled, assigned, unassigned, review_requested, review_request_removed
pull_request_merged¶
Triggered when PR is merged.
Payload: Same as pull_request_opened with:
{
"action": "closed",
"pull_request": {
"state": "closed",
"merged": true,
"merged_at": "2025-01-25T12:00:00Z",
"merged_by": {
"login": "merger_username"
}
}
}
Filter to only merged PRs:
pull_request_closed¶
Triggered when PR is closed (merged or without merge).
Use pull_request.merged field to distinguish:
- merged: true - PR was merged
- merged: false - PR was closed without merging
Comment Events¶
comment_created¶
Triggered when comment is created on issue or PR.
Event Type: comment_created
Payload:
{
"action": "created",
"comment": {
"id": 111222333,
"body": "This looks good to me! LGTM 👍",
"user": {
"login": "commenter_username",
"id": 45678
},
"created_at": "2025-01-25T13:00:00Z",
"updated_at": "2025-01-25T13:00:00Z",
"html_url": "https://github.com/acme/my-repo/issues/42#issuecomment-111222333"
},
"issue": {
"number": 42,
"title": "Issue title",
"state": "open",
"html_url": "https://github.com/acme/my-repo/issues/42"
},
"repository": { ... },
"sender": { ... }
}
Note: For PR comments, issue field still exists (GitHub treats PR comments as issue comments internally).
Access in prompt:
Comment on Issue #{{trigger_event.payload.issue.number}}
Author: {{trigger_event.payload.comment.user.login}}
Comment: {{trigger_event.payload.comment.body}}
URL: {{trigger_event.payload.comment.html_url}}
comment_updated¶
Triggered when comment is edited.
Payload: Same as comment_created with action: "edited".
Push Events¶
push¶
Triggered when commits are pushed to a repository.
Event Type: push
Payload:
{
"ref": "refs/heads/main",
"before": "abc123def456",
"after": "def456ghi789",
"created": false,
"deleted": false,
"forced": false,
"commits": [
{
"id": "def456ghi789",
"message": "Fix critical bug in payment processing",
"timestamp": "2025-01-25T14:00:00Z",
"author": {
"name": "Developer Name",
"email": "dev@example.com",
"username": "dev_username"
},
"added": ["src/payment.py"],
"removed": [],
"modified": ["src/config.py"]
}
],
"head_commit": {
"id": "def456ghi789",
"message": "Fix critical bug in payment processing",
"timestamp": "2025-01-25T14:00:00Z",
"author": { ... }
},
"repository": { ... },
"pusher": {
"name": "pusher_username",
"email": "pusher@example.com"
},
"sender": { ... }
}
Extract branch name:
To get just "main", you'll need agent to parse it.
Access in prompt:
Pushed to: {{trigger_event.payload.ref}}
Commits: {{trigger_event.payload.commits}}
Author: {{trigger_event.payload.head_commit.author.name}}
Message: {{trigger_event.payload.head_commit.message}}
Files changed: {{trigger_event.payload.head_commit.modified}}
Release Events¶
release¶
Triggered when release is published.
Event Type: release
Payload:
{
"action": "published",
"release": {
"id": 123456,
"tag_name": "v1.2.0",
"name": "Version 1.2.0",
"body": "## Changes\n\n- Feature A\n- Bug fix B",
"draft": false,
"prerelease": false,
"created_at": "2025-01-25T15:00:00Z",
"published_at": "2025-01-25T15:00:00Z",
"author": {
"login": "releaser_username"
},
"html_url": "https://github.com/acme/my-repo/releases/tag/v1.2.0"
},
"repository": { ... },
"sender": { ... }
}
Access in prompt:
New release: {{trigger_event.payload.release.tag_name}}
Title: {{trigger_event.payload.release.name}}
Notes: {{trigger_event.payload.release.body}}
URL: {{trigger_event.payload.release.html_url}}
GitLab Events¶
Common Fields¶
All GitLab events include:
{
"object_kind": "merge_request|issue|note|push|pipeline|etc",
"project": {
"id": 123,
"name": "my-project",
"path_with_namespace": "acme/my-project",
"web_url": "https://gitlab.com/acme/my-project",
"default_branch": "main"
},
"user": {
"id": 456,
"username": "username",
"name": "User Name",
"email": "user@example.com"
}
}
Merge Request Events¶
merge_request_opened¶
Event Type: merge_request_opened
Payload:
{
"object_kind": "merge_request",
"event_type": "merge_request",
"user": { ... },
"project": { ... },
"object_attributes": {
"id": 123456,
"iid": 42,
"title": "Add new feature",
"description": "## Changes\n\nAdded feature X",
"state": "opened",
"merged_at": null,
"merge_status": "can_be_merged",
"detailed_merge_status": "mergeable",
"draft": false,
"work_in_progress": false,
"source_branch": "feature/new-feature",
"target_branch": "main",
"source_project_id": 123,
"target_project_id": 123,
"author_id": 456,
"assignee_id": 789,
"assignee_ids": [789],
"reviewer_ids": [111, 222],
"labels": [
{
"id": 1,
"title": "feature",
"color": "#428bca"
}
],
"milestone_id": null,
"created_at": "2025-01-25T10:00:00Z",
"updated_at": "2025-01-25T10:00:00Z",
"url": "https://gitlab.com/acme/my-project/-/merge_requests/42"
},
"assignees": [
{
"id": 789,
"username": "assignee_username",
"name": "Assignee Name"
}
],
"reviewers": [
{
"id": 111,
"username": "reviewer1"
}
],
"labels": [
{
"id": 1,
"title": "feature",
"color": "#428bca"
}
]
}
Access in prompt:
MR !{{trigger_event.payload.object_attributes.iid}}: {{trigger_event.payload.object_attributes.title}}
Description: {{trigger_event.payload.object_attributes.description}}
Branch: {{trigger_event.payload.object_attributes.source_branch}} → {{trigger_event.payload.object_attributes.target_branch}}
URL: {{trigger_event.payload.object_attributes.url}}
Author: {{trigger_event.payload.user.username}}
State: {{trigger_event.payload.object_attributes.state}}
Merge Status: {{trigger_event.payload.object_attributes.detailed_merge_status}}
merge_request_merged¶
Payload: Same structure with:
{
"object_attributes": {
"state": "merged",
"merge_status": "merged",
"merged_at": "2025-01-25T11:00:00Z",
"merged_by_id": 333
}
}
merge_request_approved¶
Triggered when MR receives approval (GitLab-specific).
Payload: Same as merge_request_opened with additional approval info.
Issue Events¶
issue_opened¶
Event Type: issue_opened
Payload:
{
"object_kind": "issue",
"event_type": "issue",
"user": { ... },
"project": { ... },
"object_attributes": {
"id": 789012,
"iid": 25,
"title": "Bug: Login page not loading",
"description": "## Steps to Reproduce\n\n1. Navigate to /login\n2. Page shows white screen",
"state": "opened",
"author_id": 456,
"assignee_ids": [789],
"labels": [
{
"id": 2,
"title": "bug",
"color": "#d73a4a"
}
],
"milestone_id": null,
"created_at": "2025-01-25T12:00:00Z",
"updated_at": "2025-01-25T12:00:00Z",
"url": "https://gitlab.com/acme/my-project/-/issues/25"
},
"assignees": [
{
"id": 789,
"username": "assignee_username"
}
],
"labels": [
{
"id": 2,
"title": "bug"
}
]
}
Access in prompt:
Issue #{{trigger_event.payload.object_attributes.iid}}: {{trigger_event.payload.object_attributes.title}}
Description: {{trigger_event.payload.object_attributes.description}}
URL: {{trigger_event.payload.object_attributes.url}}
Labels: {{trigger_event.payload.labels}}
Comment Events (Notes)¶
comment_created¶
Comments in GitLab are called "notes".
Event Type: comment_created
Payload:
{
"object_kind": "note",
"event_type": "note",
"user": { ... },
"project": { ... },
"object_attributes": {
"id": 111222,
"note": "This looks great! Approved.",
"noteable_type": "MergeRequest",
"author_id": 456,
"created_at": "2025-01-25T13:00:00Z",
"updated_at": "2025-01-25T13:00:00Z",
"noteable_id": 42,
"url": "https://gitlab.com/acme/my-project/-/merge_requests/42#note_111222"
},
"merge_request": {
"id": 123456,
"iid": 42,
"title": "MR title",
"url": "https://gitlab.com/acme/my-project/-/merge_requests/42"
}
}
Access in prompt:
Comment on MR !{{trigger_event.payload.merge_request.iid}}
Author: {{trigger_event.payload.user.username}}
Comment: {{trigger_event.payload.object_attributes.note}}
URL: {{trigger_event.payload.object_attributes.url}}
Pipeline Events¶
pipeline¶
Triggered when CI/CD pipeline status changes.
Event Type: pipeline
Payload:
{
"object_kind": "pipeline",
"object_attributes": {
"id": 123456,
"ref": "main",
"tag": false,
"sha": "abc123def456",
"status": "success",
"stages": ["build", "test", "deploy"],
"created_at": "2025-01-25T14:00:00Z",
"finished_at": "2025-01-25T14:15:00Z",
"duration": 900,
"source": "push"
},
"merge_request": {
"id": 42,
"iid": 42,
"title": "MR title",
"source_branch": "feature-branch",
"target_branch": "main"
},
"user": { ... },
"project": { ... },
"commit": {
"id": "abc123def456",
"message": "Commit message",
"timestamp": "2025-01-25T14:00:00Z",
"author": {
"name": "Author Name",
"email": "author@example.com"
}
}
}
Status values: created, waiting_for_resource, preparing, pending, running, success, failed, canceled, skipped, manual
Access in prompt:
Pipeline: {{trigger_event.payload.object_attributes.status}}
Branch: {{trigger_event.payload.object_attributes.ref}}
Duration: {{trigger_event.payload.object_attributes.duration}}s
MR: {{trigger_event.payload.merge_request.title}}
Jira Events¶
Common Fields¶
All Jira events include:
{
"webhookEvent": "jira:issue_created|jira:issue_updated|etc",
"timestamp": 1706184000000,
"user": {
"self": "https://your-domain.atlassian.net/rest/api/2/user?accountId=...",
"accountId": "557058:...",
"displayName": "User Name",
"emailAddress": "user@example.com"
}
}
Issue Events¶
issue_opened¶
Event Type: issue_opened
Payload:
{
"webhookEvent": "jira:issue_created",
"timestamp": 1706184000000,
"issue_event_type_name": "issue_created",
"user": { ... },
"issue": {
"id": "12345",
"key": "PROJ-123",
"self": "https://your-domain.atlassian.net/rest/api/2/issue/12345",
"fields": {
"summary": "Application crashes on startup",
"description": "## Steps to Reproduce\n\n1. Launch app\n2. Crash occurs immediately",
"issuetype": {
"id": "10001",
"name": "Bug",
"iconUrl": "..."
},
"status": {
"id": "10000",
"name": "To Do",
"statusCategory": {
"key": "new"
}
},
"priority": {
"id": "3",
"name": "Medium"
},
"assignee": {
"accountId": "557058:...",
"displayName": "Assignee Name",
"emailAddress": "assignee@example.com"
},
"reporter": {
"accountId": "557058:...",
"displayName": "Reporter Name"
},
"labels": ["bug", "critical"],
"created": "2025-01-25T10:00:00.000+0000",
"updated": "2025-01-25T10:00:00.000+0000"
}
}
}
Access in prompt:
Jira Issue: {{trigger_event.payload.issue.key}}
Summary: {{trigger_event.payload.issue.fields.summary}}
Description: {{trigger_event.payload.issue.fields.description}}
Type: {{trigger_event.payload.issue.fields.issuetype.name}}
Priority: {{trigger_event.payload.issue.fields.priority.name}}
Status: {{trigger_event.payload.issue.fields.status.name}}
Assignee: {{trigger_event.payload.issue.fields.assignee.displayName}}
Reporter: {{trigger_event.payload.issue.fields.reporter.displayName}}
Labels: {{trigger_event.payload.issue.fields.labels}}
issue_updated¶
Event Type: issue_updated
Payload: Same as issue_opened with additional changelog field:
{
"webhookEvent": "jira:issue_updated",
"changelog": {
"items": [
{
"field": "status",
"fieldtype": "jira",
"from": "10000",
"fromString": "To Do",
"to": "10001",
"toString": "In Progress"
}
]
},
"issue": { ... }
}
Access in prompt:
Issue updated: {{trigger_event.payload.issue.key}}
Changes: {{trigger_event.payload.changelog.items}}
Old status: {{trigger_event.payload.changelog.items[0].fromString}}
New status: {{trigger_event.payload.changelog.items[0].toString}}
Event Filters¶
Filter Configuration¶
When configuring tracker triggers, you can add filters to narrow when flows trigger.
Available Filters:
| Filter | Applies To | Description |
|---|---|---|
| Author/Creator | All | Username who created the issue/PR/MR |
| Assignee | All | Who it's assigned to |
| Reviewer | PR/MR only | Requested reviewer |
| Labels | All | Must have ALL specified labels |
| Milestone | GitHub/GitLab | Milestone name |
| Priority | Jira only | Priority level |
| Issue Type | Jira only | Issue type name |
| State | PR/MR | State (open, closed, merged) |
| Draft | PR/MR | Draft status |
| Merged | PR/MR | Merge status |
| Mergeable State | GitHub PR | Mergeable state |
Filter Logic¶
- All filters are AND: All conditions must match
- Labels are OR: Any label in the list matches
- Empty filters match everything
Example Filter Combinations¶
Only critical bugs from team members:
Only merged PRs to main branch:
Only ready-for-review MRs from backend team:
Event: merge_request_opened
Filters:
draft: false
author: backend-dev-1,backend-dev-2,backend-dev-3
labels: [backend]
Only high-priority Jira bugs:
Template Variable Reference¶
Accessing Nested Fields¶
Use dot notation to access nested fields:
{{trigger_event.payload.issue.user.login}}
{{trigger_event.payload.object_attributes.title}}
{{trigger_event.payload.pull_request.head.ref}}
Arrays¶
Reference array elements (agent needs to parse):
Labels: {{trigger_event.payload.issue.labels}}
First label: {{trigger_event.payload.issue.labels[0].name}}
Tip: Let the AI agent parse arrays in the prompt rather than trying complex template syntax.
Conditional Logic¶
Template variables don't support conditional logic. Instead, write prompts that handle all cases:
Process this event:
Title: {{trigger_event.payload.issue.title}}
State: {{trigger_event.payload.issue.state}}
If state is "open", add "triaged" label.
If state is "closed", post a thank you comment.
Testing Triggers¶
Test Run with Custom Data¶
When using Test Run on flows with template variables:
- Click Test Run button
- Fill in values for each
{{trigger_event.*}}variable - Click Run Test
Example:
trigger_event.payload.issue.title: "Test Issue"
trigger_event.payload.issue.number: 42
trigger_event.payload.issue.user.login: "testuser"
Test Webhooks with curl¶
curl -X POST 'YOUR_WEBHOOK_URL' \
-H 'Content-Type: application/json' \
-d '{
"test": true,
"data": {
"amount": 500,
"recipient": "test@example.com"
}
}'
Test Tracker Events¶
Trigger real events in your tracker (GitHub, GitLab, Jira): - Create a test issue - Open a test PR - Add a comment
Watch the flow execution in Preloop.