How to format Jira Automation messages for a Google Chat webhook
Jira Automation has no built-in Google Chat action, so most teams use the Send web request action with a Google Chat incoming webhook. Getting a message to arrive is easy. Getting the issue key, a clickable link and one thread per issue takes the right JSON. Here are working examples you can paste, and the errors people usually hit.
Before you start
- A Google Chat space with an incoming webhook. Open the space name, then Apps & integrations, then Webhooks. Webhooks can only be set up in Chat on the web, not in the mobile app. Full steps are in the Jira to Google Chat guide.
- Google Workspace Business or Enterprise, with incoming webhooks allowed by your Workspace admin. Free Gmail accounts cannot create them.
- Permission to create Automation rules in the Jira project, or a Jira admin for global rules.
Treat the webhook URL like a password. Anyone who has it can post into the space, so do not paste it into tickets, wiki pages or public repositories.
Step 1: set up the Send web request action
- Create a rule with a trigger such as Work item created (shown as Issue created on some sites), Work item transitioned or Comment added.
- Add the Send web request action.
- Web request URL: paste the webhook URL.
- HTTP method:
POST. - Web request body: Custom data.
- Header:
Content-Typewith the valueapplication/json; charset=UTF-8.
Step 2: a text message with the issue key and a link
This is the question that comes up most on the Atlassian Community: how to get the issue key and summary into the message. Use Jira smart values inside the JSON:
{
"text": "*{{issue.key}}* <{{issue.url}}|{{issue.summary.jsonEncode}}>\nStatus: {{issue.status.name}}, priority: {{issue.priority.name}}\nAssignee: {{issue.assignee.displayName}}"
}
Three details make this work:
.jsonEncodeescapes quotes and line breaks in the summary. Without it, a summary likeLogin "Remember me" brokenproduces invalid JSON and the request fails.- Webhook messages use Google Chat's own markup by default, not standard Markdown. Bold is a single asterisk (
*bold*), italic is an underscore (_italic_), and a link with custom text is<url|text>. Double asterisks or[text](url)show up as literal characters. \ninside the JSON string starts a new line in Chat.
If the issue is unassigned, the assignee smart value is simply empty, so the line ends after the label.
Step 3: keep one thread per issue
By default every webhook call starts a new conversation, so a busy issue scatters across the space. Google Chat webhooks can reply into a thread you name with a threadKey. Using the issue key as the thread key keeps every update for that issue together.
- Add this to the end of the webhook URL in the action:
&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD. With it, Chat replies in the thread if it exists and starts it if it does not. - Add a
threadobject to the body:
{
"text": "{{comment.author.displayName}} commented on <{{issue.url}}|{{issue.key}}>:\n{{comment.body.abbreviate(300).jsonEncode}}",
"thread": { "threadKey": "{{issue.key}}" }
}
Use the same threadKey in every rule that posts about issues (created, transitioned, commented) and they all land in one thread. In a space that does not use threads, Google ignores the thread key. abbreviate(300) keeps long comments short. For service desk projects, check that internal notes cannot be posted this way; see the JSM alerts guide.
Step 4: a card with an Open in Jira button
Cards look tidier than text and can carry a button. Webhooks are one way, so buttons can only open links. Anything that needs a reply from Chat, such as an Assign to me button, needs a full Chat app.
{
"text": "{{issue.key}} {{issue.summary.jsonEncode}}",
"cardsV2": [{
"cardId": "jira-issue",
"card": {
"header": {
"title": "{{issue.key}}: {{issue.summary.jsonEncode}}",
"subtitle": "{{issue.issueType.name}} in {{issue.project.name}}"
},
"sections": [{
"widgets": [
{ "decoratedText": { "topLabel": "Status", "text": "{{issue.status.name}}" } },
{ "decoratedText": { "topLabel": "Priority", "text": "{{issue.priority.name}}" } },
{ "decoratedText": { "topLabel": "Assignee", "text": "{{issue.assignee.displayName}}" } },
{ "buttonList": { "buttons": [
{ "text": "Open in Jira", "onClick": { "openLink": { "url": "{{issue.url}}" } } }
] } }
]
}]
}
}],
"thread": { "threadKey": "{{issue.key}}" }
}
The plain text line is optional, but it gives people a readable line above the card. Text inside cards uses a small set of HTML tags such as <b> instead of Chat markup.
Mentions
To notify everyone in the space, put <users/all> in the text, for example "text": "<users/all> {{issue.key}} is a blocker". Mentioning one person needs their Google Chat user ID in the form <users/123456789>. Jira does not know that ID, so per person mentions mean keeping your own lookup table, which most teams skip.
Test the rule
Run the rule against a test issue, then open the rule's audit log. A successful call shows HTTP 200. If you turn on the option to wait for the response before later actions, you can also see the response body when something fails.
Common errors and fixes
- 400 Bad Request or invalid JSON payload: usually an unescaped quote or line break from a summary, description or comment. Add
.jsonEncodeto every free text smart value. Also check for a trailing comma after the last item in the JSON. - 404 or 403: the webhook was deleted, the URL was copied incompletely (it must include both the
keyandtokenparameters), or your Workspace admin turned webhooks off. - 429 Too Many Requests: Google allows 1 message per second per space, shared by all webhooks in that space. A bulk edit or bulk transition of 50 issues fires 50 rule runs at once, and some calls get rejected. Narrow the rule with a JQL condition, or send a daily digest instead of one message per change.
- Asterisks or square brackets show up as text: you are using standard Markdown. Switch to Chat markup:
*bold*and<url|text>. - Every update starts a new conversation: the
messageReplyOptionparameter is missing from the URL, or rules use different thread keys. - Nothing arrives and the audit log shows no call: the rule's conditions filtered the issue out, or the rule actor cannot see the issue.
When Automation rules get heavy
Automation and a webhook are a solid free option for a few rules. As the setup grows, the costs show: one rule per event and space, the JSON template copied into each rule, every run counting toward your plan's Automation usage, no batching when many issues change at once, and no single view of what was delivered or skipped.
Threadline for Jira does this job without hand written JSON. You paste the same webhook URL, send a test message, and route by project, event, issue type, priority, status, labels, assignee or JQL. It keeps one thread per issue, batches bursts so bulk edits stay under Google's rate limit, sends daily digests, respects quiet hours, never posts internal JSM comments, and shows every delivery and filter decision in a log. Threadline runs on Atlassian Forge, is free for up to 10 users, then $0.80 per user per month through Atlassian, and is pending Atlassian Marketplace review.
Frequently asked questions
Can Jira Automation send a message to Google Chat?
Yes. Jira Automation has no built-in Google Chat action, but the Send web request action can POST JSON to a Google Chat incoming webhook. Use the POST method, Custom data as the body and a Content-Type header of application/json.
How do I include the issue key and summary in the Google Chat message?
Use smart values in the JSON body, for example {{issue.key}} and {{issue.summary.jsonEncode}}. The jsonEncode function escapes quotes and line breaks so the request stays valid.
How do I make a clickable Jira link in Google Chat?
Webhook messages use Google Chat markup, so write the link as a URL and text separated by a pipe inside angle brackets, with {{issue.url}} as the URL and the issue key or summary as the text. Standard Markdown links show as plain text.
How do I keep all updates for one Jira issue in the same Google Chat thread?
Add messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD to the webhook URL and set thread.threadKey to {{issue.key}} in the JSON body. Every rule that uses the same thread key replies in that issue's thread.
Why do some Jira Automation webhook calls to Google Chat fail with 429?
Google Chat allows 1 message per second per space across all its webhooks. Bulk edits fire many rule runs at once and exceed it. Narrow the rule, use a digest, or use a tool that batches bursts.