Webhooks

A webhook is a user-defined callback over HTTP. You can use JIRA webhooks to notify your add-on or web application when certain events occur in JIRA. For example, you might want to alert your remote application when an issue has been updated or when sprint has been started. Using a webhook to do this means that your remote application doesn't have to periodically poll JIRA (via the REST APIs) to determine whether changes have occurred.

On this page:

Overview

A webhook in JIRA is defined by the following information, which you need to provide when registering (i.e. creating) a new webhook:

  • a name for the webhook created ("Webhook for my remote app")
  • the URL where the callback should be sent
  • the scope of the webhook, either "all issues" or a limited set of issues specified by JQL ("project = TEST and fixVersion = future")
  • the events to post to the URL, either "all events" or a specific set of events

A simple webhook might look like this:

Name: "My simple webhook"
URL: http://www.myremoteapp.com/webhookreceiver
Scope: all issues
Events: all issue events

 

A more complex webhook might look like this:

Name: "A slightly more advanced webhook"
URL: http://www.myremoteapp.com/webhookreceiver
Scope:
Project = JRA AND fixVersion IN ("6.4", "7.0")
Events: Issue Updated, Issue Created

Registering a webhook

To register (i.e. create) a webhook, you can use any of the following methods:

Registering a webhook via the JIRA administration console

  1. Navigate to the JIRA administration console > System > Webhooks (in the Advanced section).
    You can also use the quick search (keyboard shortcut: .), then type 'webhooks'. 
  2. Click Create a webhook.
  3. Enter the details for your new webhook in the form that is shown. For more information on this, see Configuring a webhook below.
  4. Click Create to register your webhook.

Registering a webhook via the JIRA REST API

To register a webhook via REST:

  1.  POST a webhook in JSON format to:
    <JIRA_URL>/rest/webhooks/1.0/webhook

    {
      "name": "my first webhook via rest",
      "url": "http://www.example.com/webhooks",
      "events": [
        "jira:issue_created",
        "jira:issue_updated"
      ],
      "jqlFilter": "Project = JRA AND resolution = Fixed",
      "excludeIssueDetails" : false
    }
  2. The response will return the webhook in JSON with additional information, including the user that created the webhook, the created timestamp, etc.

To unregister (i.e. delete) a webhook via REST:

  • Execute a DELETE to the following URL:
    <JIRA_URL>/rest/webhooks/1.0/webhook/{id of the webhook} 

    The following would delete the webhook with an ID of 70:

    curl --user username:password -X DELETE -H "Content-Type: application/json" <JIRA_URL>/rest/webhooks/1.0/webhook/70

To query a webhook via REST:

  • To get all webhooks for a JIRA instance, perform a GET with the following URL: <JIRA_URL>/rest/webhooks/1.0/webhook.

    curl --user username:password -X GET -H "Content-Type: application/json" http://jira.example.com/rest/webhooks/1.0/webhook
  • To get a specific webhook by its ID, perform a GET with the following URL: <JIRA_URL>/rest/webhooks/1.0/webhook/<webhook ID>

    The following would get a webhook with an ID of 72:

    curl --user username:password -X GET -H "Content-Type: application/json" http://jira.example.com/rest/webhooks/1.0/webhook/72

Configuring a webhook

The information in this section will help you configure a webhook, whether you are creating a new one or modifying an existing one.

Registering events for a webhook

The following events are available for JIRA webhooks. The string in parentheses is the name of the webhookEvent in the response.

Issue related:

  • Issue...
    • created (jira:issue_created)
    • updated (jira:issue_updated)
    • deleted (jira:issue_deleted)
    • worklog changed (jira:worklog_updated)
    Note: This event fires if a worklog is updated or deleted
  • Issue link...
    • created (issuelink_created)
    • deleted (issuelink_deleted)
    Note: Available in JIRA 7.5, or later.
  • Worklog...
    • created (worklog_created)
    • updated (worklog_updated)
    • deleted (worklog_deleted)
  • Comment...
    • created (comment_created)
    • updated (comment_updated)
    • deleted (comment_deleted)
    Note: Available in JIRA 7.1, or later.


Project-related:

  • Project...
    • created (project_created)
    • updated (project_updated)
    • deleted (project_deleted)
  • Version...
    • released (jira:version_released)
    • unreleased (jira:version_unreleased)
    • created (jira:version_created)
    • moved (jira:version_moved)
    • updated (jira:version_updated)
    • deleted (jira:version_deleted)
    • merged (jira:version_deleted)
    Note: This is the same webhookEvent name as the 'deleted' event, but the response will include a mergedTo property


User-related:

  • User...
    • created (user_created)
    • updated (user_updated)
    • deleted (user_deleted)

 

JIRA configuration-related:

  • Feature enabled/disabled...
    • voting (option_voting_changed)
    • watching (option_watching_changed)
    • unassigned issues (option_unassigned_issues_changed)
    • subtasks (option_subtasks_changed)
    • attachments (option_attachments_changed)
    • issue links (option_issuelinks_changed)
    • time tracking (option_timetracking_changed)

 

JIRA Software-related:

  • Sprint...
    • created (sprint_created)
    • deleted (sprint_deleted)
    • updated (sprint_updated)
    • started (sprint_started)
    • closed (sprint_closed)
  • Board...
    • created (board_created)
    • updated (board_updated)
    • deleted (board_deleted)
    • configuration changed (board_configuration_changed)

Choosing events for your webhook

If you are unsure which events to register your webhook for, then the simplest approach is to register your webhook for all events for the relevant entity (e.g. all issue-related events). Then you won't need to update the webhook if you need to handle these events in future; you can just add code in your add-on or web application once you want to react to them.

Restricting your events to a subset of issues via JQL

If you only want your webhook events to fire for a specific set of issues, you can specify a JQL query in your webhook to send only events triggered by matching issues. For example, you could register for all Issue Deleted events on issues in the Test ("TEST") Project with the 'Performance' component.

 

Note, although the JQL that uses standard JIRA fields is very performant, some custom fields, because of their implementation, can take multiple seconds to query. You should take this into account when using JQL for a webhook, as the query will be run with each event.

Variable substitution in the webhook URL

You can append variables to the webhook URL when creating or updating a webhook. The variables are listed below:

  • ${board.id} 
  • ${issue.id} 
  • ${issue.key} 
  • ${mergedVersion.id} 
  • ${modifiedUser.key} 
  • ${modifiedUser.name} 
  • ${project.id} 
  • ${project.key} 
  • ${sprint.id} 
  • ${version.id}

You can use these variables to dynamically insert the value of the current issue key, sprint ID, project key, etc, into the webhook URL when it is triggered. Consider the following example:

Say you specified the URL for your webhook with the ${issue.key} variable, like this:

http://jira.example.com/webhook/${issue.key}

If an issue with the key EXA-1 triggers a webhook, then the URL that will be used is:

http://service.example.com/webhook/EXA-1

Adding a webhook as a post function to a workflow

Webhooks can be attached as a workflow post function. This makes it easy to trigger a webhook when an issue makes a workflow transition, for instance when it gets rejected from QA or when it gets resolved.

To add a webhook as a post function to a workflow:

  1. Configure your workflow and select the desired transition in the workflow designer. For more details, see Working with workflows.
  2. Click Post functions, then click Add post function.
  3. Select Trigger a Webhook from the list of post functions and click Add.
  4. Select the desired webhook from the list of webhooks and click Add to add the webhook as a post function.

Notes:

  • If the webhook you choose is also configured to listen to events, then the webhook will be triggered twice: once for the event and once for the workflow transition. For this reason, you should always unselect all events from the webhook admin screen.
  • If a webhook is associated with a post-function, you will not be able to delete the webhook. You must disassociate it from the post-function first.

Executing a webhook

Webhooks will be run without a specific user context, e.g. all issues will be available to the webhook, rather than having them scoped to a single user. (Note the URL will also contain user parameters in the form ?user_id=(u'sysadmin',)&user_key=(u'sysadmin',) appended at the end.)

By default, a webhook will send a request with a JSON callback when it is triggered. If you don't want the JSON body sent, then you will need to select Exclude body when configuring the webhook.

At a high level, every callback contains the webhookEvent ID, the timestamp, and information about the entity associated with the event (e.g. issue, project, board, etc). Callbacks may have additional information, depending on the type of event associated with it. As an example, the structure of a callback for an issue-related event is described below:

Example: callback for an issue-related event

A callback for an issue-related event is structured like this:

{ 
	"timestamp"
 	"event"
	"user": {
			   --> See User shape in table below
	},
	"issue": { 
               --> See Issue shape in table below
	},
	"changelog" : {
			   --> See Changelog shape in table below	
	},
	"comment" : {
			   --> See Comment shape in table below  
	}
}
Issue shape
  • The same shape returned from the JIRA REST API when an issue is retrieved with NO expand parameters
  • REST API docs: Issue: Get issue
  • Example: JRA-2000
  • The issue is always present in a webhook POST
User shape
  • The same shape returned from the JIRA REST API when a user is retrieved, but without the activetimezone, or groups elements.
    • The shape of the user returned is a condensed shape from the normal user API in REST, but similar to what is returned when the user is embedded in another response.
    • For the full user details, use the JIRA REST API and query with the username.
  • REST API docs: User: Get user
  • Example:  Example for "username=brollins"
  • The user is always present in a webhook POST for issue events
Changelog shape
  • An array of change items, with one entry for each field that has been changed
  • The changelog is only provided for the issue_updated event
  • This is similar in format to the changelog you would retrieve from a JIRA issue, but without the user (since that is already in the JSON) and without the created timestamp (since that is also already in the JSON for a webhook event) 

"changelog": {
        "items": [
            {
                "toString": "A new summary.",
                "to": null,
                "fromString": "What is going on here?????",
                "from": null,
                "fieldtype": "jira",
                "field": "summary"
            },
            {
                "toString": "New Feature",
                "to": "2",
                "fromString": "Improvement",
                "from": "4",
                "fieldtype": "jira",
                "field": "issuetype"
            },
        ],
		"id": 10124
}
Comment shape
  • The same shape returned from the JIRA REST API when a comment is retrieved 
  • REST API docs: Issue: Get comments
  • Example: comment
  • The comment will be provided if a comment was provided with the change
{
	"id": 2,
 	"timestamp": "2009-09-09T00:08:36.796-0500",
	"issue": { 
		"expand":"renderedFields,names,schema,transitions,operations,editmeta,changelog",
		"id":"99291",
		"self":"https://jira.atlassian.com/rest/api/2/issue/99291",
		"key":"JRA-20002",
		"fields":{
			"summary":"I feel the need for speed",
			"created":"2009-12-16T23:46:10.612-0600",
			"description":"Make the issue nav load 10x faster",
			"labels":["UI", "dialogue", "move"],
			"priority": "Minor"
		}
	},
	"user": {
		"self":"https://jira.atlassian.com/rest/api/2/user?username=brollins",
		"name":"brollins",
		"emailAddress":"bryansemail at atlassian dot com",
		"avatarUrls":{
			"16x16":"https://jira.atlassian.com/secure/useravatar?size=small&avatarId=10605",
			"48x48":"https://jira.atlassian.com/secure/useravatar?avatarId=10605"
		},
		"displayName":"Bryan Rollins [Atlassian]",
		"active" : "true"
	},
  	"changelog": {
        "items": [
            {
                "toString": "A new summary.",
                "to": null,
                "fromString": "What is going on here?????",
                "from": null,
                "fieldtype": "jira",
                "field": "summary"
            },
            {
                "toString": "New Feature",
                "to": "2",
                "fromString": "Improvement",
                "from": "4",
                "fieldtype": "jira",
                "field": "issuetype"
            }
        ],
		"id": 10124
	},
	"comment" : {
		"self":"https://jira.atlassian.com/rest/api/2/issue/10148/comment/252789",
		"id":"252789",
		"author":{
			"self":"https://jira.atlassian.com/rest/api/2/user?username=brollins",
			"name":"brollins",
			"emailAddress":"bryansemail@atlassian.com",
			"avatarUrls":{
				"16x16":"https://jira.atlassian.com/secure/useravatar?size=small&avatarId=10605",
				"48x48":"https://jira.atlassian.com/secure/useravatar?avatarId=10605"
			},
			"displayName":"Bryan Rollins [Atlassian]",
			"active":true
		},
		"body":"Just in time for AtlasCamp!",
		"updateAuthor":{
			"self":"https://jira.atlassian.com/rest/api/2/user?username=brollins",
			"name":"brollins",
			"emailAddress":"brollins@atlassian.com",
			"avatarUrls":{
				"16x16":"https://jira.atlassian.com/secure/useravatar?size=small&avatarId=10605",
				"48x48":"https://jira.atlassian.com/secure/useravatar?avatarId=10605"
			},
			"displayName":"Bryan Rollins [Atlassian]",
			"active":true
		},
		"created":"2011-06-07T10:31:26.805-0500",
		"updated":"2011-06-07T10:31:26.805-0500"
	},  
	"timestamp": "2011-06-07T10:31:26.805-0500",
    "webhookEvent": "jira:issue_updated"
}

Response codes

If a webhook is triggered successfully, a response code of 200 is returned. All other response codes should be treated as an unsuccessful attempt to trigger the webhook.

Advanced topics

What happens if the remote system doesn't "catch" the webhook POST?

JIRA will retry sending three times, and then log an error in the log file: atlassian-jira.log. For JIRA Cloud customers, who don't have access to log files, we are investigating a way to provide more visibility into any webhook errors.

What versions of JIRA support webhooks?

JIRA 5.2 and later support webhooks. If you are using JIRA 5.2.x, be aware of the following limitations:

  Show me...
  • If you are using JIRA 5.2.1 or earlier, there are two known issues/limitations when using JQL with webhooks:
    • currentUser() function does not work as expected.
    • A JQL query may not return the desired results, if it is filtering for a field that changes frequently (see the 5.2 Upgrade Notes for a description of this issue). This means that you should not write a webhook which uses the JQL expression to look for a specific state change.

      For example, if you wanted to POST a webhook anytime an issue was changed to have a Priority of Blocker, you should not include "Priority = Blocker" in the JQL clause, but leave out priority, and filter for those events where Priority was changed to Blocker on the receiving side of the webhook. 

  • If you are using JIRA 5.2.2 or earlier, there is a known issues when using JQL with webhooks:
    • The ${issue.key} variable replacement does not work in a webhook, when the webhook is used in a workflow post function. Note, the ${issue.key} variable replacement does work when an issue event triggers the webhook.

More Resources

Atlassian blog posts:

Known issues

  • Post function web hooks will not fire if added to the Create Issue workflow transition. We recommend that you configure your web hook to fire from the issue_created event instead.
  • If you are using webhooks in JIRA Cloud, there is a known issue that restricts the port numbers that can be specified in the webhook URL. If you do not follow the guidelines below, then the webhook will not trigger.
    • If you are using HTTP and specify a port number in the webhook URL, the port number must be 80. Note, if you do not specify a port number, the webhook will still work.
    • If you are using HTTPS and specify a port number in the webhook URL, the port number must be 443. Note, if you do not specify a port number, the webhook will still work.
  • JQL filter for web hooks do not work correctly when Comment or Worklog related events are fired. See report: https://jira.atlassian.com/browse/JRA-59980

    • As a workaround, making use of the Issue Update event is possible.

 

Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport