# Jira

> Connect Jira Cloud with an account email and an unscoped API token for issue reads, file and close one issue per incident with the ticket preset, and send Jira issues in as signals.

_How-to · Updated 2026-10-26 · Describes release 0.1.164_

## Overview {#overview}

Jira plays three parts. The read side: the **Incident** and **Change** agents read issues, changes and sprints during last-change checks and correlation; the estate x-ray and the insights chat use the same connection. The ticket side: a ticket route with the `jira` preset files one issue when an AIOps incident opens, writes the analysis back as a comment and transitions it to a Done-category status when the incident resolves; the preset works on Jira Cloud. The inbound side: a Jira webhook can post issue events to the workspace, where an issue whose first component names a service the platform is already alerting on joins that incident.

Keep the parts on the right credentials: the agents read with an account that can only browse the intended projects; the ticket route writes with a separate account on a write-role connection the agents never see.

## Setup {#setup}

### Before you start {#before-you-start}

- The `datasources.manage` permission; the built-in owner and operator roles carry it.
- A dedicated Atlassian account with an unscoped API token for the agents' reads and, for tickets, a second account ([Installation](#installation)).

### Installation {#installation}

Create an API token for a dedicated account at Atlassian's account security page. The token must be **unscoped**: scoped tokens are served only through `api.atlassian.com` and answer `401` on the site URL. Tokens expire after at most one year; plan the rotation. The token inherits the account's project permissions, so give the read account *Browse projects* on the intended projects and nothing more. The ticket account also needs *Create issues*, *Add comments*, *Transition issues* and *Resolve issues* on the chosen project, and the create screen of the chosen issue type must show **Labels** and **Description** with no required field left without a default; **Check** reads all of that before it lets you save.

Jira Data Center is readable through this connection (it keeps `/rest/api/2/search`), but the ticket preset needs the Cloud search API.

### Configuration {#configuration}

1. Open **Settings · Data in → Data sources** and select **Connect datasource**.
2. Under **Type**, choose **Jira**. Enter a **Connection name**; the connected list shows it, and per-connection agent tools are named after it.
3. Fill the fields; the TLS-skip field sits under **Advanced connection settings**:

| Field (portal label) | API key | Value |
|---|---|---|
| Site URL (e.g. https://org.atlassian.net) | `url` | `https://<your-site>.atlassian.net`; a pasted browser URL is cut back to the site |
| Account email | `username` | The account the token belongs to |
| API token (unscoped) | `password` | Sent with the email as HTTP Basic; stored write-only |
| Skip TLS verify for a self-signed cert (optional — type: true) | `insecure` | Leave blank |

4. Optionally, open **Optional · describe this environment** and say in **What should AIOps know about it?** what this system is and what matters.
5. For the agents' connection, choose **Investigate only** under **Use this connection for** and select **Connect and verify**. For the ticket connection choose **Approved changes only (separate credential)** under **Use this connection for**, leave **Allow use for approved plans** off and save with **Save remediation credential**: a ticket route files and closes tickets and never runs an approved change.

The read connection through the API (`POST /api/aiops/{tenant_id}/datasources`, requires `datasources.manage`; the token goes in `secret_values`):

```json
{
  "type_key": "jira",
  "name": "jira-read",
  "description": "Engineering Jira; the OPS project tracks production changes, components name the services.",
  "config": {
    "url": "https://acme.atlassian.net",
    "username": "aiops-reader@example.com"
  },
  "secret_values": {
    "password": "<API token>"
  },
  "role": "read",
  "enabled": true
}
```

### Validation {#validation}

**Connect and verify**, and **Test** on the row later, sends `GET /rest/api/2/myself` with `Accept: application/json`; v2 answers on Cloud and Data Center. The verdicts, read from the status and the parsed body only:

| Verdict | Meaning |
|---|---|
| `ok · authenticated as <display name>` | The account was confirmed. |
| `failed · HTTP 401: Jira rejected the email or API token — check both. Tokens expire after at most one year, and scoped tokens are not supported yet: create one without scopes.` | Wrong, expired or scoped token, or the wrong email. |
| `failed · HTTP 403: Jira refused this account (it may be deactivated).` | The account exists but is refused. |
| `failed · the site answered with a web page, not the Jira API — use the site URL, e.g. https://<your-site>.atlassian.net` | The URL is not the site root. |
| `failed · HTTP <code>: Jira did not confirm the account` | Any other answer. |

**You should see** a dialog titled `<connection name> is connected` with **Connected — verified from the control plane** and, while no ticket route uses the connection, a **Use for tickets** link; the row's **Last test** later reads `ok · authenticated as <display name>`.

On a ticket-capable connection, a green **Test** also runs the saved ticket route's own **Check** and shows its result, or points at setting one up.

### If something fails {#if-something-fails}

The dialog shows **Needs a fix**, what to fix and the check's own detail; the row is saved either way. Select **Edit**, correct the field the detail names and save again, or select **Retry** once a cause outside the form (network, vendor-side permission) is fixed. Every verdict this connector produces, and what to do about it, is in [Troubleshooting](#troubleshooting) below.

## Data collected {#data-collected}

### Tools the agent gets {#tools}

- `<name>_request` — the HTTP tool against the site URL with HTTP Basic: `method`, `path`, `query`, `body`, `content_type`. On Jira Cloud issue search is `GET /rest/api/3/search/jql?jql=…&fields=…` (the older `/rest/api/3/search` answers `410`); an issue is `GET /rest/api/3/issue/<key>`.

There is no native Jira tool. Responses are capped at 20,000 characters per call; ask for `fields` and a `maxResults`.

### Read surface {#read-surface}

`GET` and `HEAD` run freely, and so do `POST` requests to `search/jql`, `search`, `approximate-count`, `bulkfetch` and `jql/parse`, matched on whole trailing path segments. Every other `POST`, `PUT` and `DELETE` — creating an issue, commenting, transitioning — is refused in an investigation, never offered for approval: `Investigation connections are read-only. This operation was not executed; prepare an incident change using a write connection and obtain approval.` Ticket writes do not go through the agent: the ticket route makes them from the write-role connection. The full rule table is under **The read/write gate in detail** in [Connections and remediation access](/help/read-and-write-roles.md#read-role-vs-write-role).

### Tickets {#tickets}

On the ticket connection's row select **Tickets**. Leave the project empty and press **Check** to list the projects the account can file into, pick one, **Check** again, then **Save ticket route** and **Send test ticket**, which files a real issue and closes it again within seconds. The `jira` preset cannot save without `project` and `issue_type_id`; **Check** adds `issue_type` and the project's `priorities`. The incident's P1–P4 becomes the project's priority by name — P1 is *Highest*, *Critical* or *Blocker*, P2 *High* or *Major*, and so on through the names the project has. A comment is capped at 32,000 characters. The route files tickets for the **Incident** agent's incidents only. The whole flow, including the API calls, is under [Ticket systems](/help/ticket-systems.md#ticket-systems) in Connections and remediation access.

### Tickets in {#tickets-in}

Point a Jira webhook at `https://<your-host>/webhook/jira/<workspace-slug>` with the token in the URL path or the `X-Webhook-Token` header, for the events `jira:issue_created` and `jira:issue_updated`; every other event, comments included, adapts to nothing. The issue's first component becomes the `service` label, so the issue joins the open incident whose alerts carry that exact value; otherwise it opens its own. The priority name maps `Highest` to `critical`, `High` to `error`, `Medium` to `warning`, `Low` and `Lowest` to `info`; a status in the `done` category resolves the signal. An issue must also name its severity, priority, assignee and who to notify — a `Severity:` and a `Notify:` line in the description, or `severity:` and `notify:` labels, for the two Jira has no field for: one that lacks any waits under **Needs you → Triage**, AIOps asks for what is missing in one internal comment, and its `jira:issue_updated` that names everything moves it on ([required fields](/help/ticket-systems.md#required-fields)). Issues the platform filed itself are recognised by their label and dropped, so there is no issue → incident → issue loop. Field by field, with the response counters and error strings: [webhook reference](/help/webhook-reference.md#jira).

Change issues (an issue type whose name contains `change`) are different: one this webhook delivers lands in the change ledger, and under unauthorized-change detection (`aiops_unauthorized_change_incidents`, off by default) it accounts for a captured write only when it arrives with the workspace's ITSM webhook token instead of the shared webhook token. Sent with the shared token, it is recorded and never covers a write, so a workspace with detection on sees the writes its tickets covered flagged until the sender uses the ITSM token ([The ITSM webhook token](/help/changes-reference.md#unauthorized)).

## Troubleshooting {#troubleshooting}

| What you see | Cause | What to do |
|---|---|---|
| `failed · HTTP 401: Jira rejected the email or API token …` | A scoped token, an expired token, or the wrong email. | Create an unscoped token for the account and rotate it on **Edit**. |
| `failed · the site answered with a web page, not the Jira API …` | The URL points at a page, not the site root. | Enter `https://<your-site>.atlassian.net`. |
| A `GET /rest/api/3/search` answers `HTTP 410` | Jira Cloud retired that path. | Use `/rest/api/3/search/jql`. |
| The connection turns red after a ticket call | A refusal was followed by an identity read that was refused too: the token is wrong or expired. | Rotate the token; the next green **Test** clears it. A single refused request (a project permission) stays on the incident instead. |
| **Check** shows a red line and **Save** stays disabled | A missing project permission, or a create screen with a required field and no default, or without **Labels** or **Description**. | Fix the project or the screen; **Check** again. |
| The incident page says **Ticket filing failed: …** or **Writing back … failed: …** | A refused request. | Read the reason, press **Retry**. |
| A `POST /rest/api/3/issue` through the agent answers `Investigation connections are read-only.` | The write gate. | Expected; filing is the ticket route's job. |
| An issue sent in opens its own incident instead of joining | Its first component does not equal the alerts' `service` value character for character. | Align the component name, or map it with `label_map`. |

The generic verdict strings are explained in [Test a connection and read the failure](/help/manage-connections.md#troubleshooting). Every connection status word is in the [status and error reference](/help/status-and-error-reference.md#connection-statuses).

## Next steps {#next-steps}

- Select **Discover this connection** in the success dialog to find the services and dependencies behind it: [Launch a scan](/help/estate-harvest-and-xray.md#launch-a-scan).
- File one Jira issue per AIOps incident and close it on resolve: [Tickets](#tickets).
- Send Jira issues in as signals: [Tickets in](#tickets-in).
- See what else each agent needs in [Choose your connection](/help/choose-your-connection.md#agent-needs).
