Listener Advanced Configuration
Limited Preview: Webhook Triggers & Listener
Webhook Triggers and the Webhook Listener are currently in Limited Preview and may change without notice. Access is invite-only. Self-nomination form is here. Production use is approved but may be subject to interruptions or breaking changes.
A Listener is Moveworks’ receiver for incoming webhook requests. Creating a listener gives you a Webhook URL that external systems can POST to; Moveworks validates the request, turns it into an event, and can trigger one or more plugins.
New to webhooks? Use the Webhook Triggers Quickstart for end-to-end setup and a minimal example. This page focuses on listener capabilities — especially the Advanced Configurations.
Advanced Configurations
Use these controls to harden, scope, and de-noise incoming traffic before it becomes a Moveworks event.
1. Payload Schema (Optional)
What it does: Validates the structure and types of the incoming body (LP focus: JSON) so requests that don’t match fail fast. Also supports mapping fields for downstream use.
Here’s an example of what a minimal schema could look like for Github issue events:
Example schema: Here’s an example of what a minimal schema could look like for Github issue events:
JSON
{
"action": "string",
"issue": {
"title": "string",
"html_url": "string",
"user": { "login": "string" }
},
"repository": { "full_name": "string" }
}
JSON Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"action": {
"type": "string"
},
"issue": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"html_url": {
"type": "string"
},
"user": {
"type": "object",
"properties": {
"login": {
"type": "string"
}
},
"required": [
"login"
]
}
},
"required": [
"title",
"html_url",
"user"
]
},
"repository": {
"type": "object",
"properties": {
"full_name": {
"type": "string"
}
},
"required": [
"full_name"
]
}
},
"required": [
"action",
"issue",
"repository"
]
}
Start from an actual payload (see Quickstart for how to grab it) and keep the schema minimal— only what your plugins need.
2. Listener-Level Event Filtering (ignoring noisy events)
What it does: We support filtering at both the listener level (drop noise before it is processed as an event in Moveworks) and the plugin level (conditional execution of a plugin). At the listener level, DSL filters act as a gatekeeper: if the filter evaluates to false
, the event is discarded before before being processed by Moveworks.
How it works: Write expressions against the request payload, headers, and query params to decide if Moveworks should create an event.
To understand how to use the DSL filters here let's start with an example payload. Suppose we’re listening to a Jira webhook for newly created issues. The payload might look like this:
{
"root": {
"error_message": "",
"headers": {
"map": {
"X-Jira-Event": "issue_created",
"X-Jira-Delivery": "def456",
"Content-Type": "application/json",
"User-Agent": "Atlassian-Jira-Hookshot/7.0"
}
},
"http_method": "POST",
"listener_metadata": {
"request_id": "aaaaa-bbbbb-cccc",
"listener_id": "xxxxx-yyyyy-zzzzz",
"listener_name": "My_Jira_Issue_Listener"
},
"parsed_body": {
"event_type": "issue_created",
"issue": {
"id": "JIRA-1234",
"summary": "Critical bug in login flow",
"priority": "High",
"status": "Open",
"assignee": "jdoe",
"created_at": "2025-08-17T12:30:00Z"
},
"project": {
"key": "ENG",
"name": "Engineering"
},
"user": {
"id": "56789",
"name": "Jane Doe",
"email": "[email protected]"
}
},
"query_params": {},
"raw_body": "<RAW_WEBHOOK_PAYLOAD>",
"received_at": "2025-08-17T12:30:00Z"
}
}
Paths in the event model
Moveworks represents the entire incoming HTTP request as a structured object. Given that, that the DSL paths you’ll reference look like this:
parsed_body
→ the parsed JSON payload (most typical)headers
→ all HTTP headersquery_params
→ any query string valuesraw_body
→ the unparsed body string (you likely will not use this)
Based on this some common listener-level filters might be:
Below are some specific event filter examples but see our full DSL Reference for more details on the syntax for MW DSL and other common examples.
Example filters on parsed_body
(most typical)
parsed_body
(most typical)Only process newly created issues
parsed_body.event_type == "issue_created"
Only open issues
parsed_body.issue.status == "Open"
High-priority tickets only
parsed_body.issue.priority == "High"
Tickets assigned to a specific user
parsed_body.issue.assignee == "jdoe"
Only tickets from the Engineering project
parsed_body.project.key == "ENG"
Filter by creation date (last 7 days)
parsed_body.issue.created_at.$PARSE_TIME() > $TIME().$ADD_DATE(0, 0, -7)
Example Filters on headers
headers
Why use headers?
- Some providers encode event type, signatures, or content-type in headers.
- Good for coarse routing before parsing payloads (or to enforce security checks).
Require a Jira delivery ID for traceability
headers.map["X-Jira-Delivery"] != null
Block specific sender agent
"hookshot" NOT IN $LOWERCASE(headers.map["User-Agent"])
Examples: Compounds
High-priority, open issues in ENG project only
parsed_body.issue.priority == "High"
and parsed_body.issue.status == "Open"
and parsed_body.project.key == "ENG"
Env = prod AND summary contains “security”
query_params["env"] == "prod"
AND "security" IN $LOWERCASE(parsed_body.issue.summary)
Why filter at the Moveworks listener-level at all? Some webhook providers can’t pre-filter events. If that is the case, listener event filters in Moveworks eliminate noise and keep downstream config simple.
3. Verification (Security)
Protect the endpoint so only trusted senders can trigger your workflows. Why this matters? Without verification, anyone who knows your URL can attempt to trigger your workflow; unsecured listeners are heavily rate-limited compared to secured ones.
- Signature verification (HMAC) — recommended. Configure a shared secret to verify origin and integrity.
- Auth header — require a bearer/API token header on every request.
Rate limits: Unsecured listeners are heavily rate-limited (e.g., 1 req / 10s) vs. much higher limits for secured listeners. Secure your listener before production.
4. Redaction (Logs)
Redact secrets and PII from webhook logs. Use this to hide auth headers or sensitive fields while retaining enough context to debug.
5. Deduplication (Replay Protection)
Prevent retries or duplicate sends from triggering the same workflows.
- Configure one or more deduplication keys (e.g.,
X-GitHub-Delivery
,event.id
) and a window to drop duplicates. - Helps defend against replays alongside HMAC signatures.
6. One-Time Verification Challenge (CRC)
Some providers (Slack, Zoom, Okta, etc.) send a one-time challenge during webhook registration. Configure:
- Challenge Detection — a rule that identifies the registration request (e.g., header or payload field).
- Response — status code, headers, and body to echo or sign back as required.
Observability (where to look)
Use the Webhook Logs & Troubleshooting guide for “plugin never ran” and similar playbooks.
Updated 15 days ago