Last updatedMay 16, 2018

Webhooks

A webhook is a user-defined callback over HTTP. You can use Jira webhooks to notify your app or web application when certain events occur in Jira. For example, you might want to alert your remote application when an issue is updated or when sprint is 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.

Overview

A webhook in Jira is defined by the following information that you need to provide when registering (that is, creating) a new webhook:

  • A name for the webhook created (for example, "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: 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: www.myremoteapp.com/webhookreceiver
Scope: Project = JRA AND fixVersion IN ("6.4", "7.0")
Events: Issue Updated, Issue Created

Registering a webhook

To register a webhook, you can use any of the following methods:

  • Jira administration console.
  • Jira REST API (note that the user must have the Jira Administrators global permission).

Registering a webhook via the Jira administration console

  1. Go to Jira administration console > System > Webhooks (in the Advanced section).
    You can also use the quick search (keyboard shortcut is .), then type 'webhooks'. 
  2. Click Create a webhook.
  3. In the form that is shown, enter the details for your new webhook. For more information on this, see Configuring a webhook later on this page.
  4. To register your webhook, click Create.

Operations with a webhook via the Jira REST API

Register a webhook

To register a webhook via REST, execute POST in JSON format to the following URL:

<JIRA_URL>/rest/webhooks/1.0/webhook

1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "my first webhook via rest",
"url": "http://www.example.com/webhooks",
"events": [
  "jira:issue_created",
  "jira:issue_updated"
],
"filters": {
	"issue-related-events-section": "Project = JRA AND resolution = Fixed"
},
"excludeBody" : false
}

The response will return the webhook in JSON with additional information, including the user that created the webhook, the created timestamp, etc.

Unregister a webhook

To unregister (that is, delete) a webhook via REST, execute 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:

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

To query a webhook via REST:

  • To get all webhooks for a Jira instance, execute GET to the following URL: 

<JIRA_URL>/rest/webhooks/1.0/webhook.

1
curl --user username:password -X GET -H "Content-Type: application/json" <JIRA_URL>/rest/webhooks/1.0/webhook
  • To get a specific webhook by its ID, execute GET to the following URL: 

<JIRA_URL>/rest/webhooks/1.0/webhook/<webhook ID>

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

1
curl --user username:password -X GET -H "Content-Type: application/json" <JIRA_URL>/rest/webhooks/1.0/webhook/72
Edit a webhook

To edit a webhook, execute PUT method to the following URL:

<JIRA_URL>/rest/webhooks/1.0/webhook/{id of the webhook}

1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "my first webhook via rest",
"url": "http://www.example.com/webhooks",
"events": [
  "jira:issue_created",
  "jira:issue_updated"
],
"filters": {
	"issue-related-events-section": "Project = JRA AND resolution = Fixed"
},
"excludeBody" : false
}

Configuring a webhook

The information in this section will help you configure a webhook, whether you create a new one or modify 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 and 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 (for example, 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 app or web application when 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, using JQL you could register for all Issue Deleted events on issues in the Test ("TEST") project, which are marked with ‘Performance’ component.

 

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 add variables to the webhook URL when creating or updating a webhook. The variables are the following:

  • ${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, and so on, into the webhook URL when it is triggered.

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

1
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:

1
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. Go to workflow configuration and select the desired transition in the workflow designer. For more details, see Working with workflows.
  2. Click Post functions, and 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 remove selection of 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. For example, 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 to be sent, then you 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 (for example, issue, project, board, and so on). 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 next.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
    "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 (because that is already in the JSON) and without the created timestamp (because that is also already in the JSON for a webhook event).

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    "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.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    {
        "id": 2,
        "timestamp": 1525698237764,
        "issue": {
            "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",
            "key":"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"
        },  
        "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?

    In this case, Jira will log an error in the log file atlassian-jira.log.

    Currently there is a bug which makes Jira behave differently. You can watch JRASERVER-41388 issue for updates.

    What versions of Jira support webhooks?

    Jira 5.2 and later support webhooks. If you use Jira 5.2.x, keep in mind the following limitations:

    • If you use Jira 5.2.1 or earlier, there are two known issues and limitations when using JQL with webhooks:

      • currentUser() function does not work as expected.
      • If a JQL query filters for a field that changes frequently, it may not return the desired results (for a description of this issue, see the 5.2 Upgrade Notes).  This means that you should not write a webhook that uses the JQL expression to look for a specific state change.

        For example, if you want to POST a webhook anytime an issue is 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 use 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 that the ${issue.key} variable replacement does work when an issue event triggers the webhook.

    More Resources

    Atlassian blog posts:

    Known issues

    • Post function webhooks do 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.
    • JQL filter for web hooks does not work correctly when Comment or Worklog related events are fired. See report: jira.atlassian.com/browse/JRA-59980. As a workaround, you can make use of the Issue Update event.