Automating Jira and Confluence Search from Slack using n8n

Table of Contents

At KubeNine, documentation is an important part of our work; it helps team members to learn from others’ experiences to avoid repeating the same mistakes. We maintain detailed documentation for almost every project, hosted in Confluence and Jira. But finding what we need during a Slack conversation or a huddle often means switching tabs and breaking focus.

To solve this, we used n8n to integrate Slack with both Confluence and Jira. Now, anyone in the team can tag our Slack bot, type a query, and get instant documentation or ticket links posted back in the same Slack channel in an instant.

Slack-to-Confluence Integration

Triggering from Slack

We created a custom Slack bot and connected it to n8n via the Slack Trigger node, configured to respond to app_mention events.

When someone types a message, like @JiraConfluenceBot Kubernetes ingress config sending a payload to n8n containing:

  • text: the full message content@JiraConfluenceBot Kubernetes ingress config
  • channel: the unique ID of the Slack channel the message was posted in

We extracted the actual search query and the Slack channel using a Function node:

const fullText = $json.text || "";
const searchTerm = fullText.replace(/<@[^>]+>\s*/, "").trim();
const channelId = $json.channel || "";
return [{ json: { searchTerm, channelId } }];

This removes the bot mention and isolates the actual search term. At the same time, we capture the channelId dynamic, so the response can be posted back to the correct Slack channel—without hardcoding anything.

Querying Confluence

We used the HTTP Request node to make a direct API call to Confluence’s search endpoint:

{
  "url": "https://kubeopsconsulting.atlassian.net/wiki/rest/api/content/search",
  "authentication": "basicAuth",
  "queryParametersUi": {
    "parameter": [
      {
        "name": "cql",
        "value": "=text~\"{{$json.searchTerm}}\""
      },
      {
        "name": "expand",
        "value": "body.view"
      }
    ]
  }
}

We opted for the HTTP node instead of the Confluence node because it gave us:

  • Direct access to custom CQL queries
  • Better control over parameters like pagination, filters, or expand fields
  • A consistent structure for both Confluence and Jira queries

Formatting and Posting the Response

We formatted the top 3 search results in a simple markdown format using a Function node, stripping HTML tags and generating URLs:

const baseUrl = "https://kubeopsconsulting.atlassian.net";
const items = $json.results || [];
const channelId = $node["Extract Search Term"].json["channelId"];

const formatted = items.slice(0, 3).map((item, index) => {
  const title = item.title;
  const url = `${baseUrl}/wiki${item._links.webui}`;
  const excerpt = (item.body?.view?.value || "")
    .replace(/<[^>]+>/g, '')
    .replace(/\s+/g, ' ')
    .trim()
    .slice(0, 200);

  return `*${index + 1}. ${title}*\n_${excerpt}..._\n<${url}>`;
});

return [{
  json: {
    summary: `*Search Results*\n\n${formatted.join('\n\n')}`,
    channelId
  }
}];

And finally, the message is posted to Slack using the Slack node, with the response sent to the exact channel the request came from, using:

"channelId": "={{$json.channelId}}",
"text": "={{$json.summary}}"

This dynamic binding ensures{{$json.channelId}} that the message doesn’t end up in a hardcoded or wrong channel, making the workflow channel-agnostic and reusable.

 

Slack-to-Jira Integration

We followed a similar pattern for Jira:

  1. We extract the search query and channel ID
  2. The HTTP Request node hits Jira’s /rest/api/2/search endpoint with a custom JQL query:
  3. We format the issues and generate links using:
const url = `${baseUrl}/browse/${key}`;
  1. We use {{$json.channelId}} again to send the result to the correct channel

No part of the workflow needs to know ahead of time which Slack channel the message came from—it always responds back contextually.

Using ChatGPT to Speed Up Workflow Creation

To reduce setup time, we used ChatGPT to generate:

  • JSON snippets for HTTP Request nodes
  • Function node logic to extract search terms
  • Slack formatting templates

This allowed us to build workflows faster, test logic before dropping into the n8n UI, and maintain version-controlled JSON for each bot integration.

Conclusion

With this setup, we eliminated unnecessary tab switching and made our knowledge base instantly accessible. Whether it's Kubernetes runbooks or open Jira tasks, team members can find what they need without ever leaving Slack. And because the workflows are dynamic, they can scale to any number of channels without modification.